Idee für Wettbewerb: Künstlicher-Komponist-Programm

Hier kann alles mögliche diskutiert werden. Themen zu Purebasic sind hier erwünscht.
Flames und Spam kommen ungefragt in den Mülleimer.
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Ohne Abschweifen zu wollen

Beitrag von Xaby »

>> testet ruhig mal den Befehl
http://www.gwbasic.at/index.htm

Und noch ein schöner BasicDialekt: http://www.kc85emu.de/
Dieser besitzt einen sehr eigenwilligen SOUND-Befehl mit 6 Angaben statt nur 2en.
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
Xaby
Beiträge: 2144
Registriert: 12.11.2005 11:29
Wohnort: Berlin + Zehdenick
Kontaktdaten:

Hier ist er

Beitrag von Xaby »

VERSION 1.0 meines ZufallsMusik-Machers

:mrgreen:

Code: Alles auswählen

;PlayMusik(ZufallsMusik(7,2,8))
PlayMusik("l8") ; TempieEinstellung l4 entspannung, l8 genmaeszigt, l16 flott
;ZufallsMusik(7,3,7)
ZufallsMusik(10,4,20)
:allright: Keine Sorge, für alle die dachten: :freak: :o ???

Hier ist der Rest:

Code: Alles auswählen

Procedure ZufallsMusik(Pat.l,vari.l,not.l)
  Zufall.s
  Dim Musik.l(Pat)
  Dim Melo.s(vari)
    For i=0 To  Pat
      Musik(i)=Random(Random(vari))
    Next
    For u=0 To vari
       k=0  
       c=Random(not)
       Melo(u)="o"+Chr(49+Random(6)); Chr(48+Random(8))
       Repeat
         Melo(u)=Melo(u)+Chr(Random(8)+65); TonLaenge wird noch nicht variiert
         k+1
       Until k>c
    Next

   For i=0 To Pat
     PlayMusik(Melo(Musik(i)))
   Next

  ProcedureReturn Zufall
EndProcedure
Aber ich bin ja immer noch nicht fertig.
Nun folgt der Code, der was machen tut:

Wie vorher beschrieben, das sogenannte PLAY("")
Mit einem eigenen Beispiel

Code: Alles auswählen

;{- Information
;Autor : Folker Linstedt / FL-Studios
;Code  : FLSMUSIC.INC ... Unit / Klasse / Include fuer Musik in Form von Noten ... >> Ausbaufaehig <<
;Anfang: 30.04.2006
;Stand : 30.04.2006
;/}

;{- GLOBAL ... muss irgendwie noch anders geregelt werden
Global Oktave.l
Global TonLaenge.l
Global MusikRealTonLaenge.l
Global MGesamtTempo.l

Global MusikPausenZaehler.l
Global PlayVolume.l
Global MPEffekt.l;  { Pause zwischen den Toenen }
Global PlayWithMPeffektPause.b
Global InstrumentNr.l; Ist fuer die MIDI-Unterstuetzung, kann zwischen den 128 Standard-Instrumenten
;umgeschaltet werden, oder eigene durch spezielle Verzerunngen

TonLaenge  =4
Oktave = 3
MusikRealTonLaenge.l=30000; 30000 ist wohl in Ordnung
MGesamtTempo.l=1600
PlayWithMPeffektPause=0
MPEffekt=10

;}/

Procedure NotenPause(p.l)
  Delay(p); Hier muss eine andere Pause integriert werden
EndProcedure

Procedure PLAYNOTE(N.s,Oktav.b,TonLaeng.l); Note
     f.f;
     x.f;
 ;  Debug TonLaeng
   If (N="N")
      NotenPause(TonLaeng)
   Else ; Endif ganz unten
    
; { Frequenz der einzelnen Toene ... mal Oktave ...                     }
   Select N
   Case  "C"  : f = 261.63
   Case  "#C" : f = 277.65
   Case  "C+" : f = 277.65
   Case  "D-" : f = 277.65
   Case  "D"  : f = 293.67  
   Case "#D"  : f = 311.65  
   Case "D+"  : f = 311.65  
   Case "E-"  : f = 311.65 
   Case  "E"  : f = 329.63 
   Case  "F"  : f = 349.23  
   Case "#F"  : f = 370.615 
   Case "F+"  : f = 370.615 
   Case "G-"  : f = 370.615 
   Case  "G"  : f = 392.00 
   Case "#G"  : f = 416.00  
   Case "G+"  : f = 416.00  
   Case "A-"  : f = 416.00  
   Case  "A"  : f = 440.00  
   Case "#A"  : f = 466.94  
   Case "A+"  : f = 466.94  
   Case "B-"  : f = 466.94  
   Case "H-"  : f = 466.94  
   Case "B"   : f = 493.88 
   Case "H"   : f = 493.88 
   EndSelect
   ; { (2^Oktave) 2 hoch Oktave }

   x=Pow(2,Oktav-3)
   
   GanzZahl.l=Round(f*x,0); Beep_() ist sehr empfindlich gegenueber Float, und Round liefert float
 ;  Debug f
  Beep_(GanzZahl,TonLaeng); Wenn SoundAusgabe und TonLaenge von einander unabhaengig sind ...
  ;If PlayWithMPeffektPause : NotenPause(p) : Else : NotenPause(TonLaeng-MPEffekt) : EndIf
   
   If MPEffekt>0 ; Ergibt nur Sinn, wenn 
   ;  NoSound   
     NotenPause(MPEffekt)
   EndIf
    
    ; TastenAbbruch-Funktion fehlt 
    ; Hier koennten andere Musik-OutPuts eingebunden werden
    ; z.B.: CreateSound() ... WriteToDisk() ... PlayMidi() ... 
    
    ;Denkbar waere auch eine Visualisierung in Form von NOTEN auf einem NotenBlatt dargestellt
   
   EndIf ; gehoert zu IF N="N"
EndProcedure

Dim Lis.s(3)

Procedure ZahlStellen(ss.s,pos.l)
  Anz=0
  s.s
  s=Mid(ss,pos+1,Len(ss)-pos)
  l=Len(s)
  For i=1 To l
     If Asc(Mid(s,i,1))>=48 And Asc(Mid(s,i,1))<=57
       Anz+1
       Else
       Break
     EndIf
    Next
 
  ProcedureReturn Anz
EndProcedure

Procedure Liz(s.s,pos.l)
  zahl.l
  hs.s
  hs=Mid(s,pos+1,4)
  hs=Mid(s,pos+1,ZahlStellen(s,pos)+1)
  zahl=Val(hs)
  ProcedureReturn zahl
EndProcedure
 
Procedure PlayMusik(Li.s)

  x.b; Zaehlervariable
  Li=UCase(Li)
  Li=Li+Chr(255)
  m=Len(Li)
  p=1 ; Position
  richtigeTonLaenge.l
  Repeat
    Lis(0)=Mid(Li,p+0,1): Lis(1)=Mid(Li,p+1,1): Lis(2)=Mid(Li,p+2,1): Lis(3)=Mid(Li,p+3,1)
     If Lis(0)="W" : PlayMusik("z0m5l4o3t1600") : EndIf ; Standard Wiederherstellen
     
     richtigeTonLaenge=( MGesamtTempo * 10000 ) / MusikRealTonLaenge
    
      For x=0 To 7
       If Lis(0)=Chr(65+x)
         If (Lis(1)="-") Or (Lis(1)="+")
              PLAYNOTE(Lis(0)+Lis(1),Oktave,richtigeTonLaenge);
               p+1;  Halbtonschritt hoehere Toene
             Else
             PLAYNOTE(Lis(0),Oktave,richtigeTonLaenge);
           Break;
         EndIf;
         EndIf
       Next  
      
    If (Lis(0)="P") Or (Lis(0)="N") : PLAYNOTE("N",Oktave,richtigeTonLaenge) : EndIf
    
        If Lis(0)=">" 
           Oktave+1
           If Oktave>8 : Oktave=0 : EndIf
         EndIf;
    
        If Lis(0)="<" 
           Oktave-1
           If Oktave<0 : Oktave=8 : EndIf
         EndIf;

       If (Lis(0)="#") And (Lis(1)<>Chr(255))
          PLAYNOTE("#"+Lis(1),Oktave,richtigeTonLaenge);
           p+1
       EndIf;
     
       If Lis(0)="O"
         Oktave=Val(Lis(1));
          p+1;
         EndIf;
         
         ;{- { Berechnung der Notenlaenge, mormal und punktiert }
       If Lis(0)="L" 
         If Liz(Li,p)<>0 
           
               If MusikPausenZaehler = 0 
                  TonLaenge=Liz(Li,p);
                  
                  MusikRealTonLaenge=TonLaenge * 10000;
                  If ZahlStellen(Li,p)<>0 
                    If Mid(Li,p+ZahlStellen(Li,p)+1,1)= "."
                      MusikRealTonLaenge= TonLaenge * 2 * 10000 / 3;
                      p+1
                      
                    EndIf;
                  EndIf
                Else
                  TonLaenge=Liz(Li,p);
                  MusikRealTonLaenge= MusikPausenZaehler * 10000 / TonLaenge;
                    
                If ZahlStellen(Li,p)<>0 
                  If Mid(Li,p+ZahlStellen(Li,p)+1,1)= "."
                    MusikRealTonLaenge=MusikPausenZaehler * 2 * 10000 / (TonLaenge * 3);
                    p+1 
                  EndIf;
                EndIf
              EndIf;
            EndIf;
         EndIf; 
         
         ;}/

;{- Zusaetze

     If Lis(0)="T" ; Gesamt-Tempo-Aenderung.
        If Liz(Li,p)<>0 
           MGesamtTempo = Liz(Li,p);
         EndIf;
      EndIf
    
       If Lis(0)="Z" ; Zaehler / Nenner-Tausch und Bestimmung ... beeinflusst die Berechnung der Tonlaenge
         MusikPausenZaehler = Liz(Li,p) 
       EndIf
   
       If Lis(0)="I" ; Waehlt ein Instrument aus
         InstrumentNr=Liz(Li,p);
       EndIf;

       
       If Lis(0)="M" ; Fuer den Abstand zwischen den Pausen
         MPEffekt = Liz(Li,p);
       EndIf;
       
       If Lis(0)="V" ; Für die Volumenaenderung
         PlayVolume= Liz(Li,p);
       EndIf;
   
   If Lis(0)="R" ; Tauscht zwischen kleiner Pause zwischen Noten JA/NEIN
      If PlayWithMPeffektPause=0
        PlayWithMPeffektPause=1
      Else
        PlayWithMPeffektPause=0
      EndIf  
   EndIf 
;}/    
      p+1
  Until p>=m
EndProcedure

Debug "Das Boot"
;PlayMusik("t2000o3l4.fl8edefal4.>cl8<bab>c<el1g")
Debug "Axel Foley"
;PlayMusik ("l4#fl8.al8#fl16#fl8b#fel4#fl8.>#cl8<#fl16#fl8>d#c<a#f>#c#fl16<#fl8el16el8#c#gl3#fl4p>#fl8.al8#fl16#fl8b#fel4#fl8.>#cl8<#fl16#fl8>d#c<a#f>#c#fl16<#fl8el16el8#c#gl3#f")

;/ Moegliches DateiFormat
;FFTL0000  erstellt am 25.05.2001 von Folker Linstedt
;Die Ernte oder auch Popcorn
;011231124
;o4t1600
;l8dcd<al16fl8az16l5dz0>
;l8defl16el8ffl16dl8el16dl8eel16cl8dl16cl8dd
;l16<#al4>d
;l16el4f
;/

Dim Patern.b(8)
Patern(0)=0:Patern(1)=1:Patern(2)=1:Patern(3)=2:Patern(4)=3
Patern(5)=1:Patern(6)=1:Patern(7)=2:Patern(8)=4

Dim Lied.s(4)
Lied(0)="o4t1600"; TonHoehe aendern ... statt o4 = o2 z.B.
Lied(1)="l8dcd<al16fl8az16l5dz0>"
Lied(2)="l8defl16el8ffl16dl8el16dl8eel16cl8dl16cl8dd"
Lied(3)="l16<#al4>d"
Lied(4)="l16el4f"

;/ Abspielen ...  ACHTUNG angenehme AbbruchsFunktion fehlt ! ! ! Lied spielt ca. 14 Sekunden

For i=0 To 8
  PlayMusik(Lied(Patern(i)))
Next
ich hab manche Dinge ausgeklammert, da die Musik schon etwas nervig werden kann /:->

Hier nun die Anleitung, wie man die Procedure PlayMusik() benutzt:
NICHT WUNDERN. DIE HILFE hab ich aus meinem eigenen
PASCAL-Programm übernommen. Daran könnt ihr auch gleich sehen, was in der PureBasic-Portierung noch fehlt
Wer die Pascal-UNIT haben möchte, kann sich gern bei mir melden.


{ 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 ...

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


Freue mich über eure Kommentare, achja. Mein ZufallsMusikDingli() ist natürlich noch ausbaufähig.
Das geht noch nicht:
- Polyphon
- Midi / Wave / Module

- NoteneinzellängenÄnderung
- BassDrum-Einbindung
- instrumenten-Wahl bzw. Wellenzerrung
- mehr Variabilität in der gesamtLiedStruktur
- flüssige Übergänge zwischen den TeilStücken

//--------------

Aber alles im allem finde ich es einen guten Ansatz.
Würde mich freuen, wenn einer der Erfahrenen hier, den Code etwas ändert, so dass man es auch für Spiele als HintergrundMusik einbinden kann. Auch ohne CreateSound() wenn möglich
Oder eine einfache Methode, wie ich #Sounds an einander hängen kann

Vielen Dank, hoffe, ihr könnt mit dem Code was anfangen.
Müsst mir auch nicht gleich einen Schrein bauen, aber wäre schon schön.

:allright:
Kinder an die Macht http://scratch.mit.edu/
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Wenn ich ein richtig gutes selbstkomponierendes Programm braucht, das
euch in allen möglichen Stilrichtungen etwas bietet, dann schaut euch mal
Band-In-A-Box an. Die
Technik dahinter finde ich bisher unschlagbar, aber die Programmführung
ist echt grausam.

Praktisch ist das Programm gut anwendbar, wenn man das Improvisieren
auf seinem Instrument erlenen will. Man lässt eine Begleitung aus Bass,
Gitarre, Klavier, Schlagzeug, Streicher, o.ä. generieren, dazu noch eine
Melodie oder ein Solo oder beides und spielt das dann ab. Natürlich macht
es mehr Spaß, wenn man richtig improvisiert und keine Melodien abspielt.

Wenn jemand will, kann ich mal ein paar generierte Beispiel-MIDIs
hochladen oder als MP3 konvertieren.
Antworten