Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Timing problem (https://www.delphipraxis.net/159686-timing-problem.html)

EWeiss 7. Apr 2011 22:45

Timing problem
 
Ich verwende für mein Piano einen Loop um den Song zu spielen
Leider muss ich feststellen das dieser sehr CPU lastig ist.
Also 25% hab ich dann schon.

Delphi-Quellcode:
  // Starte den Song
  while PlayingSong do
  begin
    //Weiterlaufen bis die 16.tel Note (Pause) abgelaufen ist
    while GetTickCount < Tick + TempoWait do
      Winprocessmessages;

    Tick := GetTickCount;
    PlayNotes;
    DrawGraphics(WinHandle);
    hsi.nPos := StartX + XSizeMid;
    SetScrollInfo(WinHandle, SB_HORZ, hsi, True);
  end;
Ich verwende zwar Winprocessmessages damit andere prozesse weiterlaufen können
dadurch habe ich aber ein stocken im song ..

Delphi-Quellcode:
procedure WinProcessMessages;
var
  ProcMsg: TMsg;
begin
  while PeekMessage(ProcMsg, 0, 0, 0, PM_REMOVE) do
  begin
    if (ProcMsg.message = WM_QUIT) then
      Exit;
    TranslateMessage(ProcMsg);
    DispatchMessage(ProcMsg);
  end;
end;
Hat jemand nen Tip für mich wie ich das besser Händeln könnte ?

gruss

Luckie 7. Apr 2011 23:03

AW: Timing problem
 
Was hast du dagegen, wenn die CPU das macht wofür du sie gekauft hast, nämlich rechnen? So lange der Prozess CPU Zeit abgibt, wenn sie ein anderer Prozess benötigt, ist doch alles in Ordnung. Und dein ProcessMessages hat keinen Einfluss auf andere laufende Prozesse. Du hast ja selbst die Implementierung gepostet. Guck doch mal, was da passiert. Wenn du wirklich Rechenzeit abgeben willst, dann musst du Sleep aufrufen. Damit sagst du Windows, dass du den Rest deiner Zeitscheibe nicht mehr benötigst. Der Thread wird dann schlafen gelegt und die Rechenzeit kann von einem anderen Thread in einem anderen Prozess genutzt werden.

EWeiss 7. Apr 2011 23:05

AW: Timing problem
 
Zitat:

Zitat von Luckie (Beitrag 1093784)
Was hast du dagegen, wenn die CPU das macht wofür du sie gekauft hast, nämlich rechnen? So lange der Prozess CPU Zeit abgibt, wenn sie ein anderer Prozess benötigt, ist doch alles in Ordnung. Und dein ProcessMessages hat keinen Einfluss auf andere laufende Prozesse. Du hast ja selbst die Implementierung gepostet. Guck doch mal, was da passiert. Wenn du wirklich Rechenzeit abgeben willst, dann musst du Sleep aufrufen. Damit sagst du Windows, dass du den Rest deiner Zeitscheibe nicht mehr benötigst. Der Thread wird dann schlafen gelegt und die Rechenzeit kann von einem anderen Thread in einem anderen Prozess genutzt werden.

Schon recht manche Dinge benötgen halt Rechenzeit und das geht auf die CPU.
Mich stört halt nur das die Anwendung bzw.. der Song dann stockt.

Meinst das kann man nicht verhindern ?

gruss

Namenloser 7. Apr 2011 23:11

AW: Timing problem
 
Du könntest mal die Delay-Funktion(en) aus der CodeLib probieren, wobei du erstere natürlich auf NonVCL umschreiben musst, was aber kein großes Problem sein sollte.

Ob das Timing präzise genug ist, um Musik damit abzuspielen, musst du ausprobieren.

BUG 7. Apr 2011 23:12

AW: Timing problem
 
Vielleicht wird es besser, wenn man anstelle einer Schleife einen Multimediatimer benutzt?
Der sollte dafür gemacht sein.

Luckie 7. Apr 2011 23:12

AW: Timing problem
 
Windows hat ein präemtives Multitasking System implementiert. Das heißt Windows teil den Threads Rechenzeit zu und entzieht sie ihnen auch wieder. Dadurch dass die Zeitscheiben, die ein Thread zur Nutzung der CPU zustehen, kurz gehalten sind, entsteht der Eindruck, dass Threads parallel laufen. Dabei ist für jeden Thread die Zeitscheibe gleich groß. Über das Setzen der Priorität kann man jetzt beeinflussen, wie oft ein Thread eine Zeitscheibe zugeteilt bekommt. Das nur mal zum Verständnis.

Du verursachst das Stcoken selber. Mit deinem Aufruf von ProcessMessages veranlasst du den Thread dazu die Schleife zu unterbrechen und Nachrichten aus der Nachrichtenschlange mit der Nachrichtenschleife abzuholen und zu verarbeiten. Ruf ProcessMessages nur alle 10 oder 100 oder 500 Schleifendurchläufe auf.

EWeiss 7. Apr 2011 23:32

AW: Timing problem
 
Zitat:

Du verursachst das Stcoken selber. Mit deinem Aufruf von ProcessMessages veranlasst du den Thread dazu die Schleife zu unterbrechen und Nachrichten aus der Nachrichtenschlange mit der Nachrichtenschleife abzuholen und zu verarbeiten. Ruf ProcessMessages nur alle 10 oder 100 oder 500 Schleifendurchläufe auf.
Ja ist mir klar weil halt die anderen Prozesse auch ihren Zeitraum benötigen um ihre Arbeit abzuschließen.
Es ist definitiv so wenn ich die Schleife belasse kann ich selbst mit Winprocessmessages die Anwendung nicht mehr schließen.

Selbst eine PostQuitMessage(0) schafft es nicht diesen Loop zu Unterbrechen.
Ich muss quasi das Lied erst über den Button beenden wenn ich die Anwendung schließen will.

Das war mit eines der probleme warum ich das Timing problem angesprochen habe.

Ob es mit dem Multimediatimer funktioniert müßte ich mal versuchen.
Denke aber das er letztendlich auch nicht schneller ist wie der loop selbst.

Könnte mir aber mehr zeit lassen für andere dinge anstelle von Winprocessmessages.
Wobei die Frage ist ob dieser nicht das gleiche macht um anderen Prozessen Zeit zu verschaffen.

gruss

himitsu 7. Apr 2011 23:37

AW: Timing problem
 
Ein
Delphi-Quellcode:
Sleep(0);
gibt die Verarbeitung sofort an andere Threrads ab und beim nächsten Durchlauf wird sofort weitergearbeitet.
Wenn dein Programm wirklich für eine kurze Zeit nicht zu tun hat, kannst du damit die Rechenleistung an andere Programme weiterreichen.

Bei Multiprozessorsystemen sollte Windows dein exzesiv rechnendes Programm, bzw. deinen Thread auf einem Kern laufen lassen und nahezu alle anderen Threads auf die restlichen Kerne verteilen ... dann sollten die anderen Programme auch nicht mehr gestört werden.

Und wie schon gesagt, kannst du über die Prioritäten der anwendung und des entsprechenden Threads auch auf die CPU-auslastung Einfluß nehmen ... niedrige Priorität = mehr Zeit für Andere.

Aber egal was du machst, sobald du dein Programm irgendwie ausbremst, muß du auch damit rechnen, daß es eben ein bissl langsamer läuft und eventuell auch mal etwas stockt.

Tipp: Verschieb die Sounderzeugung in einen eigenen Thread und laß die Grafiksachen ruhig etwas langsamer rangehn (wenn die Grafik etwas/unmerklich stockt, isses ja nicht so schlimm)
und wenn es getrennt ist, dann können sich anzeige und grafik nicht mehr so leicht gegenseit sörten ... und veriß im Soundthread den "Mist" mit der Messagebehandlung.

[add]
Zitat:

Es ist definitiv so wenn ich die Schleife belasse kann ich selbst mit Winprocessmessages die Anwendung nicht mehr schließen.
Genau deswegen macht man auch rechenintensive/langwierige Dinge nicht im Hauptthread.

PS: Ein Multimediatimer ist quasi genau das Selbe wie ein TTimer (nur schneller).
Und ob ein Timer für dich die Lösung ist, mußt du selber wissen.

EWeiss 7. Apr 2011 23:38

AW: Timing problem
 
Zitat:

Zitat von NamenLozer (Beitrag 1093787)
Du könntest mal die Delay-Funktion(en) aus der CodeLib probieren, wobei du erstere natürlich auf NonVCL umschreiben musst, was aber kein großes Problem sein sollte.

Ob das Timing präzise genug ist, um Musik damit abzuspielen, musst du ausprobieren.

Delphi-Quellcode:
procedure Delay(msecs: Longint);
var
  targettime: Longint;
  Msg: TMsg;
begin
  targettime := GetTickCount + msecs;
  while targettime > GetTickCount do
    if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
    begin
      if Msg.message = WM_QUIT then
      begin
        PostQuitMessage(Msg.wParam);
        Break;
      end;
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
end;
Macht fast genau das gleiche wie ich es eh schon verwende ;)

gruss

Luckie 7. Apr 2011 23:39

AW: Timing problem
 
Zitat:

Zitat von EWeiss (Beitrag 1093792)
Ja ist mir klar weil halt die anderen Prozesse auch ihren Zeitraum benötigen um ihre Arbeit abzuschließen.

Nein! Mit dem Aufruf von ProcessMessages gibst du anderen Prozessen KEINE Rechenzeit. Du veranlasst nur deinen eigenen Thread dazu die anstehenden Nachrichten abzuarbeiten.

Und wie unterbricht die Schaltfläche die Schleife? Dann ruf den Code doch vor dem Schließen auf.

EWeiss 7. Apr 2011 23:48

AW: Timing problem
 
Zitat:

Zitat von Luckie (Beitrag 1093796)
Zitat:

Zitat von EWeiss (Beitrag 1093792)
Ja ist mir klar weil halt die anderen Prozesse auch ihren Zeitraum benötigen um ihre Arbeit abzuschließen.

Nein! Mit dem Aufruf von ProcessMessages gibst du anderen Prozessen KEINE Rechenzeit. Du veranlasst nur deinen eigenen Thread dazu die anstehenden Nachrichten abzuarbeiten.

Und wie unterbricht die Schaltfläche die Schleife? Dann ruf den Code doch vor dem Schließen auf.

Das geht nicht habe ich versucht.
Die Messagen laufen den Loop davon.
Was ich meine ist das sie ausgeführt werden bevor der Loop beendet wird.
Denke die zeit ist einfach zu kurz.

Ich habe ja ne BOOL Variable
Delphi-Quellcode:
 while PlayingSong do
Habe meine Proc so umgeschrieben das wenn man auf den Beenden Knopf clickt
erst WM_QUIT aufgerufen wird.. dort habe ich dann veranlaßt das diese auf False gestellt wird.
Nach dem WM_QUIT noch ein WM_DESTROY und anschlie0end in der HauptAnwendung selbst PostQuitMessage(0) damit alles sauber beendet werden kann.

Aber! Kein Chance das teil läuft weiter..
Minimieren und Maximmieren das alles funktioniert auch beim spielen.

gruss

himitsu 7. Apr 2011 23:51

AW: Timing problem
 
Delphi-Quellcode:
while GetTickCount < Tick + TempoWait do
  Winprocessmessages;
Warum nicht einfach
Delphi-Quellcode:
Sleep(TempoWait);
?

In einem eigenständigen Thread hättest du damit keinerlei Propleme
und eine derartige Schleife macht absolut nix anderes, außer Rechnen und ständiges Nachsehn, ob es noch was zum Rechnen gibt. (also andere Programme können da garkeine Zeit von abgekommen, eher im Gegenteil ... du verbrätst sinnlos wertvolle Rechenzeit)


Notfalls ginge es im Hauptthread auch noch so:
Delphi-Quellcode:
Tick := GetTickCount + TempoWait;
Winprocessmessages;
Dec(Tick, GetTickCount);
if Integer(Tick) > 0 then Sleep(Tick);
Wenn dein Programm aber mal viele/langwierige Messages zu verarbeiten hat, dann stockt es aber so oder so, es sei denn man versucht immer nur soviele Nachrichten zu verarbeiten, wie in TempoWait genögend Zeit finden und verschiebt den rest auf die nächsten Schleifendurchläufe.


Fazit: Es liegt ein Designfehler vor wenn du eine derartige "Zeitkritische" Aufgabe, wie deine Soundausgabe, in den unberechenbaren Hauptthread legst.

EWeiss 7. Apr 2011 23:56

AW: Timing problem
 
Weil Tick gleicht GetTickCount und TempoWait das aktuell eingestellte Tempo ist mit welchen der Song abspielt.

Delphi-Quellcode:
  Tick := GetTickCount;

  // Starte den Song
  while PlayingSong do
  begin
    //Weiterlaufen bis die 16.tel Note (Pause) abgelaufen ist
    while GetTickCount < Tick + TempoWait do
      Winprocessmessages;

    Tick := GetTickCount;
    PlayNotes;
    DrawGraphics(WinHandle);
    hsi.nPos := StartX + XSizeMid;
    SetScrollInfo(WinHandle, SB_HORZ, hsi, True);
  end;
Delphi-Quellcode:
        ID_TRACK_TEMPO:
        begin
          MidiTracker.Tempo := SKAERO_GetTrackValue(SKAERO_GetMainItem(MainHandle, ID_TRACK_TEMPO));
          TempoWait := 1000 div round((MidiTracker.Tempo / 15));
        end;
gruss

Trebxson 7. Apr 2011 23:57

AW: Timing problem
 
Was passiert denn, wenn du alles was nicht mit dem Sound zu tun hat, raus haust. Hängt es dann immer noch?

Delphi-Quellcode:
timeout := 10000;

while (PlayingSong) do
 begin
  sleep (1000);
  PlayNotes;

  timeout := timeout - 1000;
  if (timeout < 0) then
   begin
    break;
   end;
 end;
Was genau macht PlayNotes bzw. wie ist es implementiert? Packt es die Noten in einen Puffer der dann (von was?) abgespielt wird? Oder spielt es die Noten gleich ab und blockiert damit die Schleife?

Vielleicht erzeugst du auch gerade mit dem Warten das Geruckle. Ist das Ruckeln gleichmäßig?

Du solltest erst die Ursache des Ruckeln bekämpfen und dann die anderen Sachen wie Grafik, Nachrichtenbehandlung, Tempo usw. hinzufügen.

BUG 7. Apr 2011 23:58

AW: Timing problem
 
Zitat:

Zitat von himitsu (Beitrag 1093799)
Warum nicht einfach
Delphi-Quellcode:
Sleep(TempoWait);
?

In einem eigenständigen Thread hättest du damit keinerlei Propleme
und eine derartige Schleife macht absolut nix anderes, außer rechnen und ständiges Nachsehn, ob es noch was zum Rechnen gibt. (also andere Programme können da garkeine Zeit von abgekommen)

:shock: MSDN-Library durchsuchenSleep macht genau das!

Zitat:

This function causes a thread to relinquish the remainder of its time slice [...] After the sleep interval has passed, the thread is ready to run. [...] Note that a ready thread is not guaranteed to run immediately. Consequently, the thread may not run until some time after the sleep interval elapses.

himitsu 8. Apr 2011 00:05

AW: Timing problem
 
@BUG: Ich weiß das, aber er macht ja kein Sleep. :zwinker:


also mit sleep gibt es die übrige Zeit ab
Delphi-Quellcode:
// Starte den Song
Tick := GetTickCount;
while PlayingSong do
begin
  //Weiterlaufen bis die 16.tel Note (Pause) abgelaufen ist
  {while GetTickCount < Tick + TempoWait do
    Winprocessmessages;}
  X := TempoWait - (Integer(GetTickCount) - Tick);
  if X > 0 then Sleep(X);
  Tick := GetTickCount;

  PlayNotes;
  DrawGraphics(WinHandle);
  hsi.nPos := StartX + XSizeMid;
  SetScrollInfo(WinHandle, SB_HORZ, hsi, True);
end;
TempoWait und Tick sind ebenfalls Integer

EWeiss 8. Apr 2011 00:08

AW: Timing problem
 
Es läuft nicht nur der Sound sondern gleichzeitig werden intensive Grafische funktionen (Rechenoperationen) ausgeführt die
an dem Sound gekoppelt sind die kann man nicht einfach ausblenden.

Das Grid wird gezeichnet die Abtastbar überprüft im Grid die eingegebenen Instrumente und Noten
zusätzlich werden zeitgleich noch die Tasten dazu gedrückt.

das ist alles nicht so einfach.. mal ebend was auslagern da alles zur selben zeit gebraucht wird.

Ich habe es mal mit himitsu variante versucht..
Keine Chance solange der Song läuft kann ich mein Window nicht schließen.

Wenn ich mein Window verschiebe hält der Song an.

gruss

EWeiss 8. Apr 2011 00:09

AW: Timing problem
 
Zitat:

Zitat von himitsu (Beitrag 1093804)
@BUG: Ich weiß das, aber er macht ja kein Sleep. :zwinker:


also
Delphi-Quellcode:
// Starte den Song
Tick := GetTickCount;
while PlayingSong do
begin
  //Weiterlaufen bis die 16.tel Note (Pause) abgelaufen ist
  {while GetTickCount < Tick + TempoWait do
    Winprocessmessages;}
  X := TempoWait - (Integer(GetTickCount) - Tick);
  if X > 0 then Sleep(X);
  Tick := GetTickCount;

  PlayNotes;
  DrawGraphics(WinHandle);
  hsi.nPos := StartX + XSizeMid;
  SetScrollInfo(WinHandle, SB_HORZ, hsi, True);
end;
TempoWait und Tick sind ebenfalls Integer

Ich habe es gemacht ;)
Und ich glaube dir auch.
Es bringt mir keinen vorteil.

Glaube es mir :)

Ich versuche es nochmal mit deiner neuen Variante ;)

EDIT:
Nop mit deiner letzten version kann ich gar nichts mehr machen.
Kein Fenster verschieben keinen Button drücken nur noch den Taskmanager verwenden zum beenden.


gruss

Luckie 8. Apr 2011 00:10

AW: Timing problem
 
Zitat:

Zitat von EWeiss (Beitrag 1093805)
Wenn ich mein Window verschiebe hält der Song an.

Richtig weil dann dein Thread die Nachrichtenschleife abarbeitet und da stehe eben jede Menge Nachrichten zum Neuzeichnen an.

Trebxson 8. Apr 2011 00:17

AW: Timing problem
 
Ich verstehe noch nicht so ganz die Logik.

Was passiert während des Waits? (per was auch immer) Stell die Zeit doch mal extrem hoch und schau ob die Hänger gleichmäßig sind.

Ich meine es gibt ja auch halbe, ganze Noten. Ganz zu schweigen von verschiedenen Akzenten Legato oder das Gegenstück Staccato.

Vielleicht musst du am Ende die Schleife durch rennen lassen. Wenn die Funktionen gekapselt sind werden die vermutlich bald zurück kommen, wenn die nichts zu tun haben.

Ist das ein Baukasten oder hast du dir einen solchen selbst zurecht programmiert? Vielleicht gibt es Beispiele für deine Schleife.

Wer liefert die Noten? Also woher weiß "PlayNotes" welche Noten zu spielen sind?

EWeiss 8. Apr 2011 00:19

AW: Timing problem
 
Zitat:

Zitat von Luckie (Beitrag 1093807)
Zitat:

Zitat von EWeiss (Beitrag 1093805)
Wenn ich mein Window verschiebe hält der Song an.

Richtig weil dann dein Thread die Nachrichtenschleife abarbeitet und da stehe eben jede Menge Nachrichten zum Neuzeichnen an.

Ist Richtig und soll (muss) auch so sein.
Aber nicht das ich meine Anwendung aufgrund des Loops nicht mehr schließen kann.

gruss

Trebxson 8. Apr 2011 00:21

AW: Timing problem
 
Und was macht

Delphi-Quellcode:
  // Starte den Song
  while PlayingSong do
  begin
    //Weiterlaufen bis die 16.tel Note (Pause) abgelaufen ist
//    while GetTickCount < Tick + TempoWait do

    sleep (1000);
    Winprocessmessages;

    Tick := GetTickCount;
    PlayNotes;
    DrawGraphics(WinHandle);
    hsi.nPos := StartX + XSizeMid;
    SetScrollInfo(WinHandle, SB_HORZ, hsi, True);
  end;
?

EWeiss 8. Apr 2011 00:30

AW: Timing problem
 
Zitat:

Zitat von Trebxson (Beitrag 1093810)
Und was macht

Delphi-Quellcode:
  // Starte den Song
  while PlayingSong do
  begin
    //Weiterlaufen bis die 16.tel Note (Pause) abgelaufen ist
//    while GetTickCount < Tick + TempoWait do

    sleep (1000);
    Winprocessmessages;

    Tick := GetTickCount;
    PlayNotes;
    DrawGraphics(WinHandle);
    hsi.nPos := StartX + XSizeMid;
    SetScrollInfo(WinHandle, SB_HORZ, hsi, True);
  end;
?

Entschuldige bitte aber ich denke mal gar nichts.
Und das muss ich auch gar nicht erst ausprobieren ;)

Ich glaube da hilft nur noch die Knallharte Methode.. HALT;
Und das will ich eigentlich nicht.

gruss

Trebxson 8. Apr 2011 00:35

AW: Timing problem
 
Meinst du?

Was macht denn

Delphi-Quellcode:
while true do
 begin
 end;
> Leider muss ich feststellen das dieser sehr CPU lastig ist.
> Also 25% hab ich dann schon.

4 Kerne?

Was anderes machst du mit WinProcessMessages derzeit nicht außer Nachrichten behandeln. (Es sei denn deine Implementierung sieht inzwischen anders aus.)

EWeiss 8. Apr 2011 00:41

AW: Timing problem
 
Zitat:

Zitat von Trebxson (Beitrag 1093812)
Meinst du?

Was macht denn

Delphi-Quellcode:
while true do
 begin
 end;
> Leider muss ich feststellen das dieser sehr CPU lastig ist.
> Also 25% hab ich dann schon.

4 Kerne?

Was anderes machst du mit WinProcessMessages derzeit nicht außer Nachrichten behandeln. (Es sei denn deine Implementierung sieht inzwischen anders aus.)

Dein Sleep ohne es testen zu müssen sorgt dafür das die Anwendung für 1000ms schläft quasi einfriert.
das bedeutet alle 1000ms wird dann bei mir das Fenster und alles andere was damit zu tun hat weiterverarbeitet.

Was soll das werden wenn ich mir noch ne neue Bremse mit einbaue.

Zitat:

Ist das ein Baukasten oder hast du dir einen solchen selbst zurecht programmiert? Vielleicht gibt es Beispiele für deine Schleife.
Was für ein Baukasten das ist eine nonvcl Anwendung geschrieben in reinem WinAPI auf lowlevel Basis.

Bild im Anhang.

gruss

Trebxson 8. Apr 2011 00:46

AW: Timing problem
 
Aber ob deine Anwendung 1000 ms schläft oder 1000 ms in einer Schleife rennt, anstatt Musik zu spielen, das ist aus meiner Sicht das gleiche.

Und dass die 1000 ms nur der Platzhalter für das Tempo sind, ich dachte das wäre auch ohne Kommentar zu erkennen gewesen.

Ich weiß ja nun immer noch nicht ob PlayNotes Zeit verbrät oder gleich zurück kommt.

Trebxson 8. Apr 2011 00:52

AW: Timing problem
 
Verarbeitest du auch Eingabegeräte? Soweit ich gelesen habe haben die bei der Echtzeitverarbeitung von Musik die gleichen Probleme.

Meiner Meinung nach Schreit das nach einen Thread pro Aufgabe.

Ein Thread für das Formular und Nachrichtenbehandlung.
Einer für die Grafik womit das Formular gefüttert wird (auch wenn du Fenster bewegst).
Und einer für den Ton.

Sagt dir Lugert Verlag Forte etwas? Das macht genau das was du versucht umzusetzen. Nur mit einfacher Grafik.

EWeiss 8. Apr 2011 00:53

AW: Timing problem
 
Zitat:

Zitat von Trebxson (Beitrag 1093814)
Aber ob deine Anwendung 1000 ms schläft oder 1000 ms in einer Schleife rennt, anstatt Musik zu spielen, das ist aus meiner Sicht das gleiche.

Und das die 1000 ms nur der Platzhalter für das Tempo sind, ich dachte das wäre auch ohne Kommentar zu erkennen gewesen.

Ich weiß ja nun immer noch nicht ob PlayNotes Zeit verbrät oder gleich zurück kommt.

Playnotes prüft welcher notentyp gerade verwendet wird läd dann dementsprechend die Instrumente und starte die Note.
Delphi-Quellcode:
TNoteType  = (BlankNote, StartingNote, ContinuingNote);

Nach Playnotes geht es in DrawGraphics wo mit GDI+ die grüne Abtastleiste gezeichnet wird.
Und von da aus geht es dann in die Zeichnen routine für das Grid
Delphi-Quellcode:
DrawGrid(WinHandle);

Das ist im groben der ablauf.
Und das kann ich nicht auslagern unmöglich da alles zusammenhängt.

gruss

EWeiss 8. Apr 2011 00:55

AW: Timing problem
 
Zitat:

Zitat von Trebxson (Beitrag 1093815)
Verarbeitest du auch Eingabegeräte? Soweit ich gelesen habe haben die bei der Echtzeitverarbeitung von Musik die gleichen Probleme.

Meiner Meinung nach Schreit das nach einen Thread pro Aufgabe.

Ein Thread für das Formular und Nachrichtenbehandlung.
Einer für die Grafik womit das Formular gefüttert wird (auch wenn du Fenster bewegst).
Und einer für den Ton.

Sagt dir Lugert Verlag Forte etwas? Das macht genau das was du versucht umzusetzen. Nur mit einfacher Grafik.

lade dir doch einfach mal das Virtual Piano herunter (Projekte der Forummitglieder)
wenn du sehen willst was ich da mache.

Eingabegeräte verwende ich keine.

EDit:
Forte 180.00EUR Euronen .. ;)

gruss

Trebxson 8. Apr 2011 01:05

AW: Timing problem
 
> Eingabegeräte verwende ich keine.

Schade :)

D.h. PlayNotes startet nur, aber wartet nicht auf das Ende der Note.

Die Nachrichtenbehandlung wirst du für den Empfang von CloseQueries usw. schon brauchen. Nur solltest du das mit dem Sleep () kombinieren um deinen Wunsch nach weniger Auslastung gerecht zu werden.

Ich habe die Erfahrung gemacht, wenn im Formular z.B. ein Button gedrückt wird der in eine Schleife rennt, wird für die Dauer die zweite Schleife im selben Thread nicht weiter ausgeführt (ist auch irgendwie logisch). Daher wirst du nichts anderes erwarten können, wenn du das Fenster durch die Gegend schiebst, dass die Musik stoppt.

Mit dem Beispielcode wollte ich übrigens auch nur wissen ob die übrigen Anweisungen hängen.

Das sind so die Probleme die ich bisher erlesen konnte.

Trebxson 8. Apr 2011 01:07

AW: Timing problem
 
> EDit:
> Forte 180.00EUR Euronen .. ;)

Leider... ich habe daher auch nur die Free-Version. Aber auch in dieser kann man Fenster durch die Gegend bewegen während die Musik spielt. Ich vermute jedoch die Nutzen den Miditreiber für solche Spielchen.

Trebxson 8. Apr 2011 01:15

AW: Timing problem
 
Ach, ich sehe gerade. Du hast derzeit nur eine Spur und stellst damit eine Klaviatur dar. Ist auch eine Idee. Ich dachte erst die schwarzen und weißen Linien sind bereits die Spuren und sind nur zur optischen Kennung eingefärbt.

Was machst du wenn eine zweite Spur hinzukommen soll? Zum Beispiel ein zweites Instrument?

Dann wäre es doch praktisch, wenn es sie mal geben sollte, den Grafik- und Tonthread einfach mit anderen Parametern zu starten?

EWeiss 8. Apr 2011 01:16

AW: Timing problem
 
Jo ist schade ;)

Delphi-Quellcode:
  if PlayX > SongLength then
  begin
    PlayingSong := False;
    SKAERO_SetCTLText(SKAERO_GetMainItem(MainHandle, ID_PLAY), 'Play');
  end;
der loop wird deaktiviert wenn die Abtastleiste in DrawGraphics das Ende der Songlänge erreicht hat
die vorher mit FindEndOfSong ermittelt wurde.

So wie es aussieht komme ich nicht drumherum die Anwendung nach PostQuitMessage(0) mit Halt; zu beenden.

Das der Song anhält ist normal wenn das Fenster verschoben wird darum ja auch Winprosessmessages damit
die anderen Threads weiterarbeiten können.

gruss

EWeiss 8. Apr 2011 01:17

AW: Timing problem
 
Zitat:

Zitat von Trebxson (Beitrag 1093820)
Ach, ich sehe gerade. Du hast derzeit nur eine Spur und stellst damit eine Klaviatur dar. Ist auch eine Idee. Ich dachte erst die schwarzen und weißen Linien sind bereits die Spuren und sind nur zur optischen Kennung eingefärbt.

Was machst du wenn eine zweite Spur hinzukommen soll? Zum Beispiel ein zweites Instrument?

Dann wäre es doch praktisch, wenn es sie mal geben sollte, den Grafik- und Tonthread einfach mit anderen Parametern zu starten?

Nein ich habe 8 Spuren ;)
Jede Farbe auf den linken Bunten Button (EditButton) repräsentieren eine Spur

Und jeder kannst du ein Instrument zuordnen aus der Bank ..
Die mußt du allerdings erst füllen.

Instrument aus der Bank auswählen Shift drücken und dann einen der Speicherplätze anklicken.
Danach ist das Instrument gespeichert.

gruss

Trebxson 8. Apr 2011 01:24

AW: Timing problem
 
Delphi-Quellcode:
procedure WinProcessMessages;
var
  ProcMsg: TMsg;
begin
  while PeekMessage(ProcMsg, 0, 0, 0, PM_REMOVE) do
  begin
    if (ProcMsg.message = WM_QUIT) then
      Exit;
    TranslateMessage(ProcMsg);
    DispatchMessage(ProcMsg);
  end;
end;

  // Starte den Song
  while PlayingSong do
  begin
    //Weiterlaufen bis die 16.tel Note (Pause) abgelaufen ist
    while GetTickCount < Tick + TempoWait do
      Winprocessmessages;
  ...
Mit exit beendest du ja auch nur die Ausführung der Funktion. Die while PlayingSong do-Schleife wertet das Ergebnis der Nachrichtenbehandlung nicht aus. D.h. die rennt ungestört weiter...
Rückgabewert? Oder gleich ein PlayingSong := false? kA welche Sichtbarkeit deine Variablen haben.

Nebenbei: Was passiert überhaupt wenn deine Anwendung Musik abspielt und etwas anderes (viel anderes bei Mehrkern) lastet dein System übermäßig aus?

Achso, ich mach dann erstmal Feierabend ;) 8 Spuren? Du überrascht schon wieder...

Und noch was weil ich es gerade sehe... du solltest solche Sachen wie DrawGraphics(WinHandle); nicht während des Herunterfahren der Anwendung ausführen. Und Halt wird dir vermutlich Speicherlecks bescheren...

EWeiss 8. Apr 2011 01:28

AW: Timing problem
 
Nein die rennt nicht ungestört weiter die beendet wenn die letzte note gespielt wurde.

Delphi-Quellcode:
procedure TMidiTracker.PlaySong(WinHandle: HWND);
var
  IntA: integer;

begin
  // Verschieb den Grid Ausschnitt wenn die Rote Laufleiste nicht
  // auf dem Grid sichtbar ist
  if (ColumnX < StartX) or (ColumnX > StartX + XSize) then
  begin
    StartX := ColumnX;
    EndX  := StartX + XSize;

    if StartX > 999 - XSize then
    begin
      StartX := 999 - XSize;
      EndX  := 999;
    end;
  end;

  // Starte das Spielen von der roten Laufleisten position
  PlayX := ColumnX;
  GetColumn(WinHandle, StartX);
  hsi.nPos    := StartX + XSizeMid;
  HasStarted  := False;
  JustScrolled := False;

  DrawGrid(WinHandle);

  // Reset die alte Note und die alte Instrumenten Variablen
  for IntA := 0 to 7 do
  begin
    OldNote[IntA] := -1;
    OldInst[IntA] := -1;
  end;

  // Nach dem Ende des Songs suchen
  FindEndOfSong;

  Tick := GetTickCount;

  // Starte den Song
  while PlayingSong do
  begin
    //Weiterlaufen bis die 16.tel Note (Pause) abgelaufen ist
    while GetTickCount < Tick + TempoWait do
      Winprocessmessages;

    Tick := GetTickCount;
    PlayNotes;
    DrawGraphics(WinHandle);
    hsi.nPos := StartX + XSizeMid;
    SetScrollInfo(WinHandle, SB_HORZ, hsi, True);
  end;

  // Warte auf die Beendigung der Wiedergabe von der letzten 16.tel Note
  while GetTickCount < Tick + TempoWait do
    Winprocessmessages;

  // Alle Noten Stoppen
  for IntA := 0 to 7 do
  begin
    if SKAERO_GetCheckButtonStatus(SKAERO_GetMainItem(MainHandle,
      IntA + ID_HIDETRACK_FIRST)) = False then
    begin
      channel := IntA;
      if OldNote[IntA] > -1 then
        FlipStopNote(OldNote[IntA] mod 1000);
    end;
  end;

  hsi.nPos := 0;
  hsi.nTrackPos := 0;
  StartX := 0;
  SetScrollInfo(WinHandle, SB_HORZ, hsi, True);
  DrawGrid(WinHandle);

end;
Das funktioniert und arbeite einwandfrei nach dem ich auf den Stop Button klicke
oder der Song zu ende ist.

gruss

Trebxson 8. Apr 2011 01:36

AW: Timing problem
 
> Nein die rennt nicht ungestört weiter die beendet wenn die letzte note gespielt wurde.

Es ging doch aber ums Beenden der Anwendung (während gespielt wird) ;) Nacht!

EWeiss 8. Apr 2011 01:37

AW: Timing problem
 
Zitat:

nicht während des Herunterfahren der Anwendung ausführen. Und Halt wird dir vermutlich Speicherlecks bescheren...
Darum geht es doch ;)
Wie soll ich das verhindern wenn ich nicht rechtzeitig bzw.. den loop beenden kann
bevor ich die Anwendung Herunterfahre.

Genau das ist mein Problem das meine Anwendung hängt und ich sie nicht beenden kann.


Zitat:

Es ging doch aber ums Beenden der Anwendung (während gespielt wird) Nacht!
Korrekt .. ;) Nacht!

gruss

himitsu 8. Apr 2011 06:41

AW: Timing problem
 
Zitat:

Zitat von Luckie (Beitrag 1093807)
Zitat:

Zitat von EWeiss (Beitrag 1093805)
Wenn ich mein Window verschiebe hält der Song an.

Richtig weil dann dein Thread die Nachrichtenschleife abarbeitet und da stehe eben jede Menge Nachrichten zum Neuzeichnen an.

Diese werden doch alle abgearbeitet? (direkt vor der kurzen Pause)

Da alles im Hauptthread abläuft, kann wärend der Zeit der Schleife Pause vom Programm auch keine neue Nachricht erzeugt werden.
Und Benutzereingaben des Benutzers werden innerhalb von maximal 62 Millisekunden abgehandelt. Für den Benutzer sollte diese Verzögerung fast garnicht auffallen.

:gruebel:

Namenloser 8. Apr 2011 09:15

AW: Timing problem
 
Zitat:

Zitat von EWeiss (Beitrag 1093795)
Zitat:

Zitat von NamenLozer (Beitrag 1093787)
Du könntest mal die Delay-Funktion(en) aus der CodeLib probieren, wobei du erstere natürlich auf NonVCL umschreiben musst, was aber kein großes Problem sein sollte.

Ob das Timing präzise genug ist, um Musik damit abzuspielen, musst du ausprobieren.

Delphi-Quellcode:
procedure Delay(msecs: Longint);
var
  targettime: Longint;
  Msg: TMsg;
begin
  targettime := GetTickCount + msecs;
  while targettime > GetTickCount do
    if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
    begin
      if Msg.message = WM_QUIT then
      begin
        PostQuitMessage(Msg.wParam);
        Break;
      end;
      TranslateMessage(Msg);
      DispatchMessage(Msg);
    end;
end;
Macht fast genau das gleiche wie ich es eh schon verwende ;)

gruss

Hagens Variante aber nicht.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:40 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz