Frequenz aus Wave

Anfängerfragen zum Programmieren mit PureBasic.
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Frequenz aus Wave

Beitrag von Andreas_S »

Wie kann ich die Frequenz aus einem Word in einer Wave-Datei herrausrechnen? Ich hab das so begonnen:

Code: Alles auswählen

Procedure.d TR_Sin(Grad.d)
 ProcedureReturn Sin(Grad*#PI/180)
EndProcedure
Procedure.d TR_ASin(Wert.d)
 ProcedureReturn ASin(Wert)/#PI*180
EndProcedure


NewList FQList()
File$=OpenFileRequester("Load Wave...","","Wave-Datein (*.wav)|*.wav;*.wave",0)
ReadFile(0,File$)
 FileSeek(0,44)
  While Eof(0)=0
   AddElement(FQList())
   actsamplevalue=ReadWord(0)
   FQList()= ? ? ?
  Wend
CloseFile(0)
 ForEach FQList()
  Debug FQList()
 Next
Beim erstellen einer Wave-Datei wird doch actsamplevalue mit dem Sinus berechnet:

Code: Alles auswählen

For acttime=1 To samplerate*ms/1000
 For actchannel=1 To channels
  actsamplevalue=32767*Sin(2*#PI*fq*acttime/samplerate)
  WriteWord(file,actsamplevalue)
 Next
Next
Das wäre dann nur noch eine Gleichung zum umrechnen, aber ich hab mich schon den 2. Tag daran gespielt und ich bekomme es nicht hin.

Danke im voraus!
Benutzeravatar
Fluid Byte
Beiträge: 3110
Registriert: 27.09.2006 22:06
Wohnort: Berlin, Mitte

Beitrag von Fluid Byte »

Frequenz aus einem Word in einer Wave-Datei herrausrechnen?
Sofern du mit Frequenz die Samplerate meinst (22KHz, 44KHz, etc.) und sofern es sich um eine gewöhnliche WAV Datei handelt musst du gar nichts rechnen sondern lediglich den Header auslesen.
Windows 10 Pro, 64-Bit / Outtakes | Derek
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Code: Alles auswählen

actsamplevalue=32767*Sin(2*#PI*fq*acttime/samplerate)
sollte für fq sein

Code: Alles auswählen

fq=(ASin(actsamplevalue/32767)*samplerate)/(2*#PI*acttime)
Gruss
Helle
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

Erstmal Danke,

Wie man den Header ausließt weis ich, aber ich mein die Raw-Daten die ab Byte 44 beginnen und in Word gesetzt sind. Da wird mit dem Sinus die Frequenz bearbeitet: Hier. Ich meine das ab den For-Schleifen da steht:

Code: Alles auswählen

ActSampleVal = $7FFF * Sin(2 * #PI * Frequency * ActTime/Samplerate)
wenn das jetzt in die Datei geschrieben wird kann man es später ja wieder auslesen und dann will ich mit der Gleichung die Frequenz ausrechnen.

Dake im voraus!
Benutzeravatar
Froggerprogger
Badmin
Beiträge: 855
Registriert: 08.09.2004 20:02

Beitrag von Froggerprogger »

Du kannst auf diese Art keine Frequenz aus einem Samplewert erhalten.
Selbst, wenn die WAV-Datei nur aus einer einzigen Sinuswelle unbekannter Frequenz besteht, liefert diese Umkehrung mit ASin nur eine mögliche Frequenz, die an dem entsprechenden Zeitpunkt denselben Samplewert annehmen würde (bei Phasenverschiebung 0) wie die gesuchte Frequenz.

Du willst aber wahrscheinlich von beliebigem Audiomaterial die "Frequenz zu einem Zeitpunkt" aus dem Samplewert heraus bestimmen, was in sich schon unlogisch ist. Du kannst lediglich innerhalb eines Zeitfensters, z.B. von 1024 aufeinanderfolgenden Samplewerten bestimmen, welche Frequenzen in diesem Zeitraum wie stark enthalten sind. Dafür nutzt man die FFT (Fast Fourier Transformation) um aus diesem Zeit/Wert-Signal ein Frequenzspektrum für das gegebene "Fenster" (den Ausschnitt) zu erhalten.

Ein PB-Source für die FFT flog schonmal irgendwo herum, war allerdings in einer sehr rudimentären Version - funktionierte, aber langsam. Je nach Anwendungszweck aber brauchbar.
Allgemein greift man da normalerweise auf externe Libraries zu. Z.B. fmod liefert die FFT des gegenwärtigen Wiedergabebuffers, ansonsten ist FFTW *die* Library für die FFT: http://www.fftw.org/
!UD2
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

Danke :allright: !

Ich hab da eine Frage: Wie stark wird sich das errechnete vom tatsächlichen Ergebnis abweichen. 1-5 könnte ich verkraften, aber ich denke nicht das sich wegen des Sinuses so viel Unterschied bildet .... oder doch?

Und noch eine: Wie kann ich vom Ergebnis des Sin() Befehls, also Sin(blabla), in ASin() eingeben das dann wieder blabla rauskommt ohne das ich im Sin(blabla) etwas anderes dazu schreiben muss?

Code: Alles auswählen

a=10
sin.d=Sin(a)
Debug sin
Debug ASin(sin)
Danke im voraus!
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Das Argument a ist ein Wert im Bogenmaß (also z.B. der Wert Pi entspricht 180°) und das Sinus-Argument wird (FPU-intern) auf einen Wert zwischen -Pi/2 und +Pi/2 umgerechnet (eigentlich Pi/4, aber das lassen wir hier mal weg). Eindeutige Ergebnisse erhält man also nur, wenn a zwischen -1,5707963267... und +1,5707963267... liegt (-+Pi/2). Vom Wert a=10 wird solange Pi/2 subtrahiert, bis es in den o.g. Werte-Bereich passt: a-(6*Pi/2)=9,42477796... und 10-9,42477796... = 0,5752220... ist dann das (Rück-)Ergebnis mit Asin(). Siehe auch (die Werte mit den vielen Nachkomma-Nullen sind praktisch Null):

Code: Alles auswählen

For x=0 To 10
a.d=x*#PI/2
sin.d=Sin(a) 
Debug sin 
Debug ASin(sin)
Debug ""
Next
Also wie Froggerprogger richtig schrieb besteht hier das Problem der Eindeutigkeit.

Gruss
Helle
Andreas_S
Beiträge: 787
Registriert: 14.04.2007 16:48
Wohnort: Wien Umgebung
Kontaktdaten:

Beitrag von Andreas_S »

Danke:allright: ,


Kann ich den Sinus von 2*2 auch trennen? Also das zB. Sin(2*2)=Sin(2) >>irgenetwas<< Sin(2) ist. Oder irgendwie anders...


Danke im voraus!
Benutzeravatar
Helle
Beiträge: 566
Registriert: 11.11.2004 16:13
Wohnort: Magdeburg

Beitrag von Helle »

Code: Alles auswählen

A.d=2
Debug Sin(2*A)
Debug 2*Sin(A)*Cos(A)
Debug ""
Debug Sin(3*A)
Debug 3*Sin(A)-4*Pow(Sin(A),3)
Debug ""
Debug Sin(4*A)
Debug 4*Sin(A)*Cos(A)-8*(Pow(Sin(A),3)*Cos(A))
Debug ""
Debug Sin(5*A)
Debug 5*Sin(A)-20*Pow(Sin(A),3)+16*Pow(Sin(A),5)
Das ist aber alles pure Mathematik ohne Bezug zu Wave!

Gruss
Helle
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Mal was in Pascal von ganz noch früher von mir

Beitrag von Xaby »

Code: Alles auswählen

{ (c) FF Technologies 1997-2003, NewSTYLE                       }
{ WAVmaker.PAS Programm, Generiert ROH-Daten fuer Audio-Ausgabe }
{ (c) Folker Linstedt 2002, designed for FF Technologies        }

{ Anfang :  03.11.2002  9:32                        }
{ Stand  :  15.12.2004 20:30h  FL  NewDATA NewSOUND } { WAVE Wiedergabe }


USES Crt, FFTDataU, FFTMusic;

VAR F: Text; N: String; SoundFormatBits: Byte; X, Y, L: LongInt;
    S: Array[0..125]of Integer; {Stri:String[252];}  Z,ZZ:LongInt; C: Char;
    Freq: LongInt; Erg: Real; W:Array[0..56000] of Byte;

 PROCEDURE SetSoundFormat(Bits:Byte;Abtastrate:Word);
   BEGIN
     SoundFormatBits:=Bits;


   END;

 PROCEDURE WriteSound( Freq:Real;Laeng:LongInt;Format:ShortInt;Lautst:Word);
 VAR L:LongInt; A, B: Char; Y: Integer; Laut: Real; I:ShortInt;
   BEGIN

   Laut:=Potenzn(2,SoundFormatBits)/200*Lautst; {Lautstaerke in Prozent }

   IF SoundFormatBits=8 then
   Begin

   IF Format=0 then
   For L:=0 to Laeng-1 do
     Begin I:=Round(128+sin(L/Laeng*2*3.1416*Freq)*Laut);A:=Char(I);Write(F,A);
     End;
   IF Format=-2 then
   For L:=0 to Laeng-1 do
     Begin I:=Round(128-sin(L/Laeng*2*3.1416*Freq)*Laut);A:=Char(I);Write(F,A);
     End;
   IF Format=1 then
   For L:=0 to Laeng-1 do
     Begin
       I:=Round(128+sin(L/Laeng*2*3.1416*Freq)*Laut);
       if I<0 then I:=I*-1;
       A:=Char(I); Write(F, A);
     End;
   IF Format=-1 then
   For L:=0 to Laeng-1 do
     Begin
       I:=Round(128+sin(L/Laeng*2*3.1416*Freq)*Laut);
       if I>0 then I:=I*-1;
       A:=Char(I); Write(F, A);
     End;
   End
   else
   IF SoundFormatBits=16 then
   Begin
   IF Format=0 then
     For L:=0 to Laeng-1 do
     Begin
       Y:=Round(sin(L/Laeng*2*3.1416*Freq)*Laut);
       B:=Char(Y DIV 256);
       A:=Char(Y MOD 256);
       Write(F, A,B);
     End;
   IF Format=-2 then
     For L:=0 to Laeng-1 do
     Begin
       Y:=Round(-sin(L/Laeng*2*3.1416*Freq)*Laut);
       B:=Char(Y DIV 256);
       A:=Char(Y MOD 256);
       Write(F, A,B);
     End;
   IF Format=1 then
     For L:=0 to Laeng-1 do
     Begin
       Y:=Round(sin(L/Laeng*2*3.1416*Freq)*Laut);
       If Y<0 then Y:=Y*-1;
       B:=Char(Y DIV 256);
       A:=Char(Y MOD 256);
       Write(F, A,B);
     End;
   IF Format=-1 then
     For L:=0 to Laeng-1 do
     Begin
       Y:=Round(sin(L/Laeng*2*3.1416*Freq)*Laut);
       If Y>0 then Y:=Y*-1;
       B:=Char(Y DIV 256);
       A:=Char(Y MOD 256);
       Write(F, A,B);
     End;


   End;
   END;

Function Speedtest:LongInt;
VAR Clo, I:LongInt;
  Begin
    Clo:=Clock; i:=0;
    While Not (Clock>Clo+1000) do Inc(I);
    SpeedTest:=I;
  End;

PROCEDURE LoadWAVE(Name:String);
BEGIN
  Assign(F,Name);
  Reset(F);
  L:=GetFileSize(Name); If L>56000 then L:=56000;
  For x:=1 to L do begin Read(F,C); W[X]:=Ord(C);
     if W[X]<128 then
             W[X]:=255-W[x] else W[X]:=W[x]-128;

  end;
  Close(F);

END;

PROCEDURE PlaySound;
VAR I:LongInt;
BEGIN
  I:=Clock;
  FOR X:=1 to L do
    Begin
      Sound(256*W[x]);
      FOR Y:=1 to 8 do if Not(Clock>I+1000) then Inc(I); { Pause }
      { NoSound; }
    End;
    NoSound;

END;


BEGIN
(* Laut:=32000; Lang:=441; {0.01 sek. bei 44100 Abtastungen/sek. }
   Schwing:=440; { Frequenz : Ton a = 440 Hz } X:=10; { 1/X sek. Stuecke }
   For L:=0 to Lang-1 do Begin R:=L/Lang*2*3.1416*Schwing/X;    { x 2 pi         }
     Y:=Round(sin(R)*Laut); { x Laut-Staerke } B:=Char(Y DIV 256);
     A:=Char(Y MOD 256); Write(F, A,B);
   End; Close(F);*){ WritePlay('geefddcdefggg',10000,'F:\Hans.Raw'); }

(*
 N:='F:\RX.Raw'; SetSoundFormat(16,44100);
 Assign(F,N);
 Rewrite(F);
 { WriteSound( Freq:Real;Laeng:LongInt;Format:ShortInt;Lautst:Word); }

   For x:=1 to 44 do
     Begin
       WriteSound( 880, 126, 0,90);
       WriteSound(7040, 126, 0,90); { 138 Frames mit 7040 Hz ideal         }
       WriteSound( 880, 126, 0,90); { stark gekrisselt                     }
       WriteSound(  10, 126, 0, 0);
       WriteSound(7040, 126, 0,90);
       WriteSound(  10, 126, 0, 0);
       WriteSound( 880, 126, 0,90);
       WriteSound(  10, 126, 0, 0);
     End;
  Close(F);

    ClrScr; TextColor(9);
    N:='C:\lied.raw'; Assign(F,N); Reset(F);

    For y:=0 to 15 do
    Begin
      For x:=1 to 252 do Read(F, C);
      Stri[x]:=C;
      Z:=0;
      For X:=1 to 126 do
        Begin
          S[X]:=ord(Stri[2*x-1])+ord(Stri[2*x])*256; {S[x]}
          if S[X]<0 then
             Z:=Z-S[X] else Z:=Z+S[X];
        End;   {    ?   }
      If ( (Z>17000) and (Z<19000) ) then TextColor(12) else
      If ( (Z>  750) and (Z< 6000) ) then TextColor( 0) else
      TextColor(11);
      Writeln(IntoNumStr(y,2),': ',z);
    End;
  Close(F);

*)

ClrScr;
{
  Freq:=440;
  For z:=0 to 200 do
    Begin
      Freq:=440+10*z;
      Erg:=10000*sin(3.1416*Freq);
      Sound(Round(Erg));
      Pause(1);
    End;
  WriteLn(Erg,' ...fertig ');
  }
{  NoSound;  ZZ:=0;
  For z:=1 to 5 do
  Begin
    X:=SpeedTest;
    ZZ:=ZZ+X;
    WriteLn(X);
  end;
  WriteLn; WriteLn(Round(ZZ / 5),' ',Round(ZZ/5/44100));
}
 LoadWave('C:\dididi.raw'{m11khz8b.raw'});
 PlaySound;

 readkey;

END.
Hoffe es hilft dir. :?

Wie man eine Wave erstellt, zu mindest eine RAW:

Code: Alles auswählen

{ FF Technologies (c) 1997-2003, designed by Folker Linstedt }
{ FFTMusic.PAS, zum Abspielen von Musik, Audio-Efecten...    }
{ Idee seit Anfang 2000, gemacht bis zum 21.10.2000 nichts   }

{ Anfang :  irgendwann 1999       }{ vom 11.12.2001-03.11.2002 unveraendert }
{ Stand  :  03.11.2002 10:50h  FL }{ Mit Schreib-Ausgabe auf Festplatte }

(*************************************************************************}
   Es werden die UNITs CTR und FFTDATAU.PAS/TPU benoetigt
 *************************************************************************

   FFTMusic wird Musik in Form von Notenfolgen ueber den PC-Speaker
            wiedergeben koennen, allerdings wird es nicht moeglich sein,
            waerend der Wiedergabe etwas anderes zu tun, da die
            Pause auf der Procedure DELAY basiert... >;-(

 *************************************************************************

  PROCEDURE PLAY(+?+);

  +?+ koennte sein Melodie/Lied/Musikstueck/Geraeusch, max. Zeichen 254,
      bei 255 kann es passieren, das der letzte Befehl nicht richtig
      ausgefuehrt wird. Letzte Zeichen sollten nur Notennamen sein


  Beispiel :  PLAY('o3l4ccddeeffl2#aphbft255cdefigah');


              W  : Standard wiederherstellen, Notenlaengen, Oktaven und
                   Zeitschalter werden auf Standard werte gesetzt.

              S  : Schaltet SoundKartenausgabe um, sollte sie deaktiviert
                   sein, so wird sie angeschaltet und andersrum

              o3 : OKTAVE    (0..8)   3 wird gesetzt
                           { 0 bis 8, aber schon fast zu
                             hoch fuer's menschliche Ohr }
                           { 2 bis 5 sind empfohlen, 2,3,4,5 }

              >/<: Durch GROESSER und KLEINER wird die aktuelle OKTAVE
                   um eine OKTAVE erhoeht bzw. erniedrigt
                   die Oktave kann nicht kleiner Null oder groesser
                   acht sein, es wird bei Ueber- oder Unterschreitung
                   wieder von vorn gezaehlt. Nach acht kommt null und
                   vor null kommt acht.


              l4 : TONLAENGE (0..999) 4 =             1/4 Note
                                      4.= punktierte  1/4 Note
                                      8 =             1/8 Note

                                      usw.

                                      2 = eine halbe      Note
                                      1 = ganze           Note
                                      0 ist unzulaessig!

               c, d, e, f, g, a, h bzw. b sind zulaessige Notennamen

                  b und h sind gleich, damit die Funktionen zur
                  engl. Notensprache nicht abweichen, aber dennoch
                  der uns bekannten gleicht


               # Raute : erhoeht eine Note um einen Halbtonschritt
              ( plus"+" )     um eine Note um einen Halbtonschritt
                              zu erniedrigen, muss der vorhergehende
                              Notenname erhoeht werden.
                              oder Minus"-"

                            Bsp.: anstatt   "des", "bd", "d" erniedriegt
                                  wird  "c" erhoeht, "cis", "#c", "c+","d-"

                        Die Raute, das Kreutz gilt nur fuer den unmittelbar
                        folgenden Ton, "#gdc" = "gis", "d", "c"



              N     Steht fuer keinen Ton, wie P
              P :   PAUSE, Laenge der Pause entspricht den Notenlaengen,
                           es koennen mehrere "P"s hintereinander stehen,
                           die Pause wird entsprechend laenger...

             M10:   Ist die Pause zwischen den Toenen. { 10 Millisec. Pause }
                    mit M0 oder U koennen spaetere Noten durch gedachte
                    Boegen verbunden werden


            T1800:   T, Tempo, Aendert das MGesamttempo,
                        wobei das Verhaeltnis der einzelnen Notenlaengen
                        zu einander gleich bleibt...
                        T ist die Laenge in Millisec. eines Taktes.

                    ZusatzEffekte sind im Moment nur die Drums, siehe unten
              Q:   Q, ZusatzEffekt, mit der Nummer 2,
                       die Zahl nach dem "Zet" kann beliebig sein,
                       die Effekte koennten zum Beispiel
                       Drums, FXs oder Fantasiegeraeusche sein...
                       diese Effekte sind mehr toenig, komplexer,
                       sie werden bei dem Aufruf des Buchstaben "Z"
                       abgespielt, sollte ein Z-Effekt nicht existieren,
                       so wird kein akustisches Signal ausgegeben, und
                       es tritt auch keine Zeitverzoegerung auf, so dass
                       ein Aufruf eines nicht vorhandenen Z-Effektes
                       keine Auswirkung auf das "Musikstueck" haben,
                       jedoch sollte eine Zeit fuer einen vorhandenen
                       Z-Effekt eingeplant werden, es kann gleichzeitig
                       nur ein Signal durch den PC-Speaker ausgegeben
                       werden, das bedeutet, dass ein nichtvorhandener
                       Effekt den Zeitplan durcheinander bringen koennte!!!

                       z.B. : 'l4ccdq3fegihcpi#a#d#ci'
                             angenommen q3 ist ein Q-Effekt, der von der
                                        TonLaenge genau einer ViertelNote
                                        entspricht, so wird
                                        das Abspielen 4 Takte dauern,
                                        sollte der Q-Effekt(Nr. 3) nicht
                                        existieren, so dauert die
                                        Wiedergabe nur 3 Takte!

                  Z :   veraendert MusikPausenZaehler!
                     Z0 veranlasst, L = Nenner, 1 = Zaehler
                     dass alle mit L angegebenen Pausen
                     1/L gross sind, da manche Pausen sich jedoch so nicht
                     dastellen lassen, kann man mit Z den Nenner bestimmen
                     und mit L bestimmt man dann die Groesse des Zaehlers.
                  Bsp. Z0L4 P=1/4 od. 4/16 Z0L16 P=1/16 Z0L8 P=1/8 od. 2/16
                    ->  3/16 kann man mit einer L8. darstellen, aber P=5/16
                        sind da schon schwieriger. Loesung: Z16L5
                        fuer normale Musikstuecke mit merkwuerdigen Pausen
                        ist Z16 empfohlen. Sollten die
                        Musikstuecke z.B. Gabba oder von
                        schnellem Perkaschen sein,
                        sind groessere Werte fuer Z besser.

                 "Drums"  und  "High Hats"         "DrumPause"
                Komma ','     Semikolon ';'        Unterstrich '_'

                I : Aendert die Ausgabe der Noten auf ein mit I angegebenes
                    Instrument, wenn M=0, dann koennen mehrere Instrumente
                    gleichzeitig gespielt werden ...

{*************************************************************************)

 UNIT FFTMUSIC;

 INTERFACE

 VAR TonLaenge, MGesamttempo, MusikRealTonLaenge : LongInt;
     MusikPausenZaehler : LongInt;
     Oktave : ShortInt; PlayGesamtV : ShortInt;
     ZMEffekt{ZusatzEffektNummer}    : Word;
                                     { M=Musik, zur Unterscheidung von
                                                anderen ZusatzEffekten! }
     MPEffekt  : Integer;  { Pause zwischen den Toenen }
     PlayWithMPeffektPause : Boolean; { Gibt an, ob die Pause vom MPEffekt
                                        zur TonLaenge adiert werden oder
                                        nicht. "R" schaltet um
                                      }

     BassDrum, HighHat, DrumPause : String;
     SavedMusikVars : Array[0..7] of LongInt;

    PlayTon : Boolean; { Wenn AnTon, dann spielt Play etwas, diese Variable
                         existiert, um nicht vor jeder Verwendung von Play
                         eine Vaiable nach dem Zusatand ueberpruefen zu
                         muessen ...                                       }
    PlayVolume : Byte; { Wirkt sich nur auf ueber Soundkarte ausgegebenen
                         FrequenzMudulierten(FM) Ton aus                   }
    PlayFM     : Boolean; { FM moeglich       }
    PlaySK     : Boolean; { momentane Ausgabe, True und PlayFM dann ueber   }
                          { ueber SoundKarten-Synthesiser, wenn PlayFM oder }
                          { PlaySK false, dann Ton ueber PC-Speaker         }
  InstrumentNr : Byte   ; { Aktuelles Instrument 0..9                       }

 PROCEDURE PLAY(LIED:STRING);
 PROCEDURE WritePLay(S:String; v:Word; D:String); { Seit 03.11.2002 }
 PROCEDURE ShutDownFM;
 PROCEDURE InitFM;
 PROCEDURE LoadFL(Pattern, AbNote, Option : Integer; Name : String);
 PROCEDURE Beep;


 IMPLEMENTATION

 USES Crt, FFTDataU, FM;
 VAR MusikDatei: Text; SchreibeMusik:Boolean; Laut:Word;

 PROCEDURE SaveMusikVars;
   Begin
     SavedMusikVars[0]:=MusikRealTonLaenge;
     SavedMusikVars[1]:=TonLaenge;
     SavedMusikVars[2]:=MGesamttempo;
     SavedMusikVars[3]:=Oktave;
     SavedMusikVars[4]:=ZMEffekt;
     SavedMusikVars[5]:=MPEffekt;
     SavedMusikVars[6]:=InstrumentNr;
     SavedMusikVars[7]:=MusikPausenZaehler;
   End;

 PROCEDURE ReStoreMusikVars;
   Begin
     MusikRealTonLaenge   :=SavedMusikVars[0];
     TonLaenge            :=SavedMusikVars[1];
     MGesamttempo         :=SavedMusikVars[2];
     Oktave               :=SavedMusikVars[3];
     ZMEffekt             :=SavedMusikVars[4];
     MPEffekt             :=SavedMusikVars[5];
     InstrumentNr         :=SavedMusikVars[6];
     MusikPausenZaehler   :=SavedMusikVars[7];
  End;

 PROCEDURE PLAYEFFEKT(Ef:String);
 VAR x, y: Word;
   BEGIN
   END;

 Procedure Beep;
   Begin
     Sound(Round(329.63*2)); { Eigentlich Write(#7), aber falls man diesen }
     Delay(100);             { Ton erzeugen will, muss man dann Write(#7); }
     NoSound;
     Delay(10);
   End;

 PROCEDURE PLAY(LIED:STRING);
 VAR X: BYTE; L1, L2: BYTE; Lis : String[4];
 FUNCTION Li: Char;
   Begin
     Li:=Lied[L2];
   End;
 FUNCTION Li2: Char;
   Begin
     Li2:=Lied[L2+1];
   End;

 FUNCTION Liz: LongInt;
 VAR Z : LongInt;
   Begin
      Z:=0;
      if ZahlStellen(Lis)=1 then Z:=IntoVal(Lis[1]);
      if ZahlStellen(Lis)=2 then Z:=IntoVal(Lis[1]+Lis[2]);
      if ZahlStellen(Lis)=3 then Z:=IntoVal(Lis[1]+Lis[2]+Lis[3]);
      if ZahlStellen(Lis)=4 then Z:=IntoVal(Lis[1]+Lis[2]+Lis[3]+Lis[4]);
      Liz:=Z;
   End;

 PROCEDURE PLAYNOTE(N{ote}:String);
 VAR P: LongInt; F{requenz} : Real; x: Real; L:LongInt; Y:Integer; A,B:Char;
     P2: LongInt;
   BEGIN
   N := IntoGrStr(N);
   P:=(( MGesamtTempo * 10000 ) DIV MusikRealTonLaenge);
                     { Dieser Faktor dient der Genauigkeit,
                       er erfordert aber auch, dass MGesamtTempo,
                       MusikRealTonLaenge und TonLaenge Typ LongInt sind }
   if Not(SchreibeMusik) then
   if (N='N') then Begin NoSound; Pause(P); Exit; End;
 { Aenderung der Arbeit und Beginn mit einer anderen Art ab 29.04.2001 }
 { Frequenz der einzelnen Toene ... mal Oktave ...                     }
   if  N='C'                                       then F:= 261.63  else
   if (N='#C') or (N='C+') or (N='D-')             then F:= 277.65  else
   if  N='D'                                       then F:= 293.67  else
   if (N='#D') or (N='D+') or (N='E-')             then F:= 311.65  else
   if  N='E'                                       then F:= 329.63  else
   if  N='F'                                       then F:= 349.23  else
   if (N='#F') or (N='F+') or (N='G-')             then F:= 370.615 else
   if  N='G'                                       then F:= 392.00  else
   if (N='#G') or (N='G+') or (N='A-')             then F:= 416.00  else
   if  N='A'                                       then F:= 440.00  else
   if (N='#A') or (N='A+') or (N='B-') or (N='H-') then F:= 466.94  else
   if (N='B' ) or (N='H' )                         then F:= 493.88  else

   Exit;

   { (2^Oktave) 2 hoch Oktave }

   if Oktave = 0 then x:=   0.125 ; { bei FM kann es Probleme geben }
   if Oktave = 1 then x:=   0.25  ; { fuer Speaker noch moeglich    }
   if Oktave = 2 then x:=   0.5   ; { nur Ton C-Dur                 }
   if Oktave = 3 then x:=   1     ; { Normal, eingestriche C-Dur    }
   if Oktave = 4 then x:=   2     ;
   if Oktave = 5 then x:=   4     ;
   if Oktave = 6 then x:=   8     ;
   if Oktave = 7 then x:=  16     ;
   if Oktave = 8 then x:=  32     ; { nicht zu empfehlen ... zu hoch }

   IF SchreibeMusik then
     Begin
       IF PlayWithMPeffektPause then P2:=P else P2:=P-MPEffekt;
       For L:=0 to Round(441*P2/10)-1 do
        Begin
          Y:=Round(sin(L/(P2*441/10)*2*3.1416*F*X)*Laut); { x Laut-Staerke }
          if (N='N') then Y:=0;
          B:=Char(Y DIV 256);
          A:=Char(Y MOD 256);
          Write(MusikDatei, A,B);
        End;
   IF MPEffekt<>0 then
      For L:=0 to Round(441*MPEffekt/10)-1 do
        Begin
          Y:=0;
          B:=Char(Y DIV 256);
          A:=Char(Y MOD 256);
          Write(MusikDatei, A,B);
        End;
        end
     Else
   IF PlayTon then
     BEGIN

       IF ( (NOT(PlayFM))  or (NOT(PlaySK)) ) then
           Sound(Round(F*x)) else
           fm_play_tone(InstrumentNr,Round(F*x),Round(playvolume-63+PlayGesamtV));
     END;
   IF Not(SchreibeMusik) then
   IF PlayWithMPeffektPause then Pause(P) else Pause(P-MPEffekt);

   IF Lied[L2+1]<>'U' THEN { U macht Bogen moeglich }
   if MPEffekt<>0 then
     begin
       NoSound; fm_stop_tone(InstrumentNr);
       if MPEffekt>0 then Pause(MPEffekt);
     end;

  END;


   BEGIN
     Lied:=IntoGrStr(Lied); {Umwandlung des Strings in Grossbuchstaben)}
     L1:=Length(Lied);
     If L1=0 then Exit  else  Lied := Lied + #255 ;
        L2:=1;

  Repeat
     Lis:=Lied[L2+1]+Lied[L2+2]+Lied[L2+3]+Lied[L2+4];

       For x:=0 to 7 do
       IF Li=Char(65+x) then
         Begin
           if (Li2='-') or (Li2='+') then
             begin
               PlayNote(Li+Li2);
               Inc(L2);  { Halbtonschritt hoehere Toene }
             end else
             PlayNote(Li);
           Break;
         End;

       IF (Li='P') or (Li='N') then PlayNote('N');

         IF Li='S' THEN PlaySK:=InvertBool(PlaySk);
         IF Li='W' THEN Play('z0m5l4o3t1800');

       IF Li='L' then { Berechnung der Notenlaenge, mormal und punktiert }
         Begin
           if Liz<>0 then
             Begin
                if MusikPausenZaehler = 0 then
                Begin
                TonLaenge:=Liz;
                MusikRealTonLaenge:=TonLaenge * 10000;
                if ZahlStellen(Lis)<>0 then
                if (Lied[L2+ZahlStellen(Lis)+1]= '.')
                then
                Begin
                   MusikRealTonLaenge:= TonLaenge * 2 * 10000 DIV 3;
                   Inc(L2);
                End;
                End else
                Begin
                  TonLaenge:=Liz;
                  MusikRealTonLaenge:=
                     MusikPausenZaehler * 10000 DIV TonLaenge;
                if ZahlStellen(Lis)<>0 then
                if (Lied[L2+ZahlStellen(Lis)+1]= '.')
                then
                Begin
                  MusikRealTonLaenge:=
                     MusikPausenZaehler * 2 * 10000 DIV (TonLaenge * 3);
                  Inc(L2);
                End;
                End;
             End;
         End;

       IF Li='O' then
         Begin
           Oktave:=IntoVal(Lied[L2+1]);
           Inc(L2);
         End;

       IF Li='I' then
         Begin
           InstrumentNr:=IntoVal(Lied[L2+1]);
           Inc(L2);
         End;

       IF Li='M' then
         Begin
           MPEffekt := Liz;
         End;
       IF Li='V' then
         Begin
           PlayVolume:= Liz;
         End;

       IF Li='T' then
         Begin
           if Liz<>0 then
           MGesamtTempo := Liz;
         End;

       IF Li='>' then
         Begin
           Inc(Oktave); if Oktave>8 then Oktave:=0
         End;

       IF Li='<' then
         Begin
           Dec(Oktave); if Oktave<0 then Oktave:=8
         End;

       IF (Li='#') and (Li2<>#0) then
         Begin
           PlayNote('#'+Li2);
           Inc(L2);
         End;

       IF Li='Z' then MusikPausenZaehler := Liz;


       IF (Li='_') or (Li=',') or (Li=';') then
       Begin
         SaveMusikVars;
           IF Li='_' then Play(DrumPause);
           IF Li=',' then Play(BassDrum );
           IF Li=';' then Play(HighHat  );
         ReStoreMusikVars;
       End;

       IF Li='R' then
          PlayWithMPeffektPause:=InvertBool(PlayWithMPeffektPause);

       Inc(L2);
   Until L2>L1;
   IF PlayFM then fm_stop_tone(InstrumentNr);
   NoSound;
   END;

  PROCEDURE LoadFL(Pattern, AbNote, Option : Integer; Name : String);
  VAR FL: Array[0..9] of String;         { Speicherabhaengig,
                                           sonst bis 255, statt 9 }
      F : Text; S : String; N : String; P : String;
      x : Integer;  K{ennung} : STRING;

      { Diffinition des Formates *.FL(FolkersLieder) wurde am 17.05.2001
        fest gelegt. Spezielle Optionen und Erweiterungen in der Benutzung
        der Prozedur LOADFL werden spaeter hinzugefuegt. Es wird nur in
        der Einstellung (*1)ALLES SPIELEN oder (*2)NUR 1 PATTERN SPIELEN
        funktionieren. Bei (*1) muessen alle Werte NULL sein.
        Bei (*2) muss OPTION EINS sein und PATTERN vorhanden. NULL ist der
        erste PATTERN!
       }
    BEGIN
      ENDUNG(NAME,'FL!');
      IF EXIST(AUDIO+NAME) then NAME:=AUDIO+NAME;
      IF EXIST(NAME) THEN
        BEGIN
            Assign(F,Name); Reset(F);
            ReadLn(F,K); { muss FFTL sein }
            IF (K[1]='F') and (K[2]='F') and (K[3]='T') and (K[4]='L') then
              BEGIN
                ReadLn(F,N); { Name des Liedes wird gelesen }
                READLN(F,P); { Unterstuetzung von maximal 255 Patternfolgen }
                { K[5] und K[6] geben die Version vom FL-Format an }
                { K[7]+1 gibt Anzahl der unterschiedlichen Patterne an }
                { K[8] gibt an, ab der wievielten IndexNr. intern gezaehlt
                  wird. So kann der Pattern(1) auch wirklich im Quellcode
                  die Zahl eins haben, wenn K[8] den Wert 48 Besitzt! Klingt
                  kompliziert, is' aber so. Dies funktioniert aber nur bei
                  10 unterschiedlichen Paternen maximal, da immer nur ein
                  Byte fuer ein Pattern zum Aufruf genutzt wird und damit
                  keine zweistellige Zahl wiederzuerkennen ist. Pattern NR.10,
                  also der 11. waere dann naemlich ein Doppelpunkt und der
                  12 Pattern ein Semikolon und so weiter ...
                  Ein Pattern selbst ist auf 255 Zeichen begrenzt, sollte
                  ein zu wiederholender Abschnitt(Pattern) nicht in einem
                  einzigen String dargestellt werden koennen, so muessen
                  mehrere dafuer benutzt werden und spaeter auch mehrere
                  wiederholt werden.
                  }
                  For x:=0 to Ord(K[7]) do { Liest alle Paterne in FL ein }
                    Begin
                      ReadLn(F,S);
                      FL[x]:=S;
                      if EoF(F) then Break;
                    End;
                  Close(F);

                  IF (Option=1) then
                    Begin
                       Play(FL[Pattern]);
                    End
                  else
  {                IF (Pattern=0) and (AbNote=0) and (Option=0) then
  }                For X:=1 to Length(P) do
                    Begin
                      S:=FL[ord(P[x])-ord(K[8])]; { zu spielender Pattern
                                  wird festgelegt und in S geschrieben, dann }
                      Play(S);   { wird er gespielt! Ganzes Lied }
                    End;
              END;                   { Nur Pattern mit Nummer PATTERN spielt }
        END;
    END;


  PROCEDURE WritePLay(S:String; v:Word; D:String);
    Begin
      SchreibeMusik:=True;
      Laut:=v;
      Assign(MusikDatei, D);
      Rewrite(MusikDatei);
      IF IOResult=0 then
        Play(S);
      Close(MusikDatei);
      SchreibeMusik:=False;
    End;


  Function InstrumentMaker(c0,c1,k0,k1,a0,a1,s0,s1,w0,w1,fb:Byte): PPatch;
    Begin
      InstrumentMaker^.chars[0]:=c0;
      InstrumentMaker^.chars[1]:=c1;
      InstrumentMaker^.ksl_lev[0]:=k0;
      InstrumentMaker^.ksl_lev[1]:=k1;
      InstrumentMaker^.att_dec[0]:=a0;
      InstrumentMaker^.att_dec[1]:=a1;
      InstrumentMaker^.sus_rel[0]:=s0;
      InstrumentMaker^.sus_rel[1]:=s1;
      InstrumentMaker^.wav_sel[0]:=w0;
      InstrumentMaker^.wav_sel[1]:=w1;
      InstrumentMaker^.fb_conn:=fb;
    End;

  Procedure InitInstruments;
    Begin
      fm_load_patch(0,fm_get_patch_piano);
      fm_load_patch(1,fm_get_patch_sine );
      fm_load_patch(2,InstrumentMaker(0,0, 0,0, 63,252, 20, 20,17, 17, 0));
      fm_load_patch(3,InstrumentMaker(0,0, 0,0, 20, 110, 40, 40, 0, 0 , 0));
      fm_load_patch(4,InstrumentMaker(0,0, 0,0, 20, 120, 0, 100, 0, 0 , 0));

    End;

 PROCEDURE ShutDownFM;
 VAR c : Byte;
   BEGIN
     For c:=0 to 8 do
       fm_stop_tone(c);
       NoSound;
   END;

  PROCEDURE InitFM;
    BEGIN
    PlayFM:=fm_detect;
    IF fm_detect then
      Begin
        fm_Reset;
        InitInstruments;
      End;
    END;

  BEGIN
  { PlaySk:=True;   }
    SchreibeMusik:=False;
    instrumentnr:=0;
    InitFM;
    PlayGesamtV:=63;
    PlayTon:=True; PlayVolume:=63; { 63 = maximal Volumen }
    PlayWithMPeffektPause := TRUE;
    Play('W');
    DrumPause :='l6p'  ;
     BassDrum :='l16.o1c';
      HighHat :='l8o7f';
    ShutDownFM;
  END.
PB:

http://www.purebasic.fr/german/viewtopi ... tenlaengen

:?
Kinder an die Macht http://scratch.mit.edu/
Antworten