  | 
					
						Das deutsche QBasic- und FreeBASIC-Forum Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!   
						
						
					 | 
				 
			 
			 
	
		| Vorheriges Thema anzeigen :: Nächstes Thema anzeigen   | 
	 
	
	
		| Autor | 
		Nachricht | 
	 
	
		S_F
 
 
  Anmeldungsdatum: 16.03.2010 Beiträge: 6
 
  | 
		
			
				 Verfasst am: 16.03.2010, 21:09    Titel: Sägezahnschwingung | 
				     | 
			 
			
				
  | 
			 
			
				Hallo
 
 
Ich bin gerade neu hier und habe schon ein erstes Problem.
 
Wie der Titel sagt will ich eine Sägezahnschwingung für ein kleines Software-Synthesizer Projekt berechnen.
 
 
 	  | Code: | 	 		  
 
Wert = (((t mod (Samplerate/Frequenz)) / (Samplerate/Frequenz)) - 0.5) * Amplitude
 
 | 	  
 
 
Mit diesem Code funktioniert das auf den ersten Blick auch ganz. Wenn ich jedoch zwei Schwingungen unterschiedlicher Frequenz addiere, z.B. 64 Hz und 256 Hz., so schwingt die höhere Frequenz nicht exakt viermal wenn die tiefere Frequenz einmal schwingt.
 
 
Dies erzeugt im Ton eine störende Schwebung.
 
Zur Berechnung werden Variabeln des Typs double verwendet.
 
 
Hat jemand eine Idee wie man eine Sägezahnschwingung anders berechnen kann oder das Problem umgehen kann?
 
 
Kritisch ist wahrscheinlich die Berechnung Samplerate/Frequenz
 
 
Vielen Dank im Voraus | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Jojo alter Rang
  
  Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
  | 
		
			
				 Verfasst am: 16.03.2010, 21:13    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				MOD arbeitet mit ganzzahlen, es wäre also sinnvoller, überall mit ganzzahlen zu arbeiten IMHO. Ansonsten wäre es ganz hilfreich, wenn du den ganzen code posten könntest. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		S_F
 
 
  Anmeldungsdatum: 16.03.2010 Beiträge: 6
 
  | 
		
			
				 Verfasst am: 16.03.2010, 21:31    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Folgender Code sollte eine .wav Datei erstellen und eine (hässlich tönende) Sägezahnschwingung rein schreiben.
 
 
mod kann nur mit Ganzzahlen rechnen!!! Natürlich!' '
 
 
Das ist wahrscheinlich das Problem. Samplerate/Frequenz wird also immer auf eine Ganze Zahl gerundet, deshalb auch die ungenaue Frequenz.
 
 
Kann man das irgendwie anders berechnen?
 
Ich möchte jedoch nicht eine Zählvariable im Stil von (if a>Samplerate/Frequenz then a = 0 und a+= 1) verwenden.
 
 
 	  | Code: | 	 		  dim Shared as integer Samplerate = 44100    'Wave relevante Angaben
 
dim Shared as integer Bittiefe = 32
 
dim Shared as integer Kanaele = 1
 
dim Shared as integer laenge = 2^19
 
 
Dim  As double Array(0 To laenge - 1)
 
dim as integer t, a, sampel
 
dim sampel2 as double
 
 
declare Function new_wave(nam as string) as integer
 
declare Function saegezahn(frequenz as double, amplitude as double, t as double) as double
 
 
for t = 1 to laenge
 
    Array(t-1) = saegezahn(128,0.8,t)
 
next
 
 
a = new_wave("Beispiel") 'Ich schreibe nicht direkt in die Datei da normalerweise noch andere Berechnungen
 
                         'durchgeführt werden (Fouriertransformation, Frequenzmodualtion etc.)
 
 
for t = 0 to laenge - 1
 
    sampel2 = Array(t) * 2^31
 
    sampel = sampel2
 
    Put #a,,sampel
 
next
 
 
Function saegezahn(frequenz as double, amplitude as double, t as double) as double
 
    saegezahn = (((t mod (Samplerate/Frequenz)) / (Samplerate/Frequenz)) - 0.5) * Amplitude
 
end function
 
 
Function new_wave(nam as string) as integer
 
    dim a as integer
 
    a = Freefile
 
    Open nam + ".wav" For Binary As #a
 
    dim f_lang as integer
 
    dim f_short as short
 
    
 
    dim as integer Blockgroesse = Kanaele * Bittiefe/8
 
    dim as integer BytesProSekunde = Blockgroesse * Samplerate
 
 
    dim f_Char as byte
 
    f_char = asc("R")
 
    Put #a,,f_char
 
    f_char = asc("I")
 
    Put #a,,f_char
 
    f_char = asc("F")
 
    Put #a,,f_char
 
    f_char = asc("F")
 
    Put #a,,f_char
 
 
    f_lang = 4+24+8+Kanaele*Laenge*Bittiefe/8
 
    Put #a,,f_lang
 
 
    f_char = asc("W")
 
    Put #a,,f_char
 
    f_char = asc("A")
 
    Put #a,,f_char
 
    f_char = asc("V")
 
    Put #a,,f_char
 
    f_char = asc("E")
 
    Put #a,,f_char
 
 
    f_char = asc("f")
 
    Put #a,,f_char
 
    f_char = asc("m")
 
    Put #a,,f_char
 
    f_char = asc("t")
 
    Put #a,,f_char
 
    f_char = asc(" ")
 
    Put #a,,f_char
 
 
    f_lang = 16
 
    Put #a,,f_lang
 
 
    f_short = 1
 
    Put #a,,f_short
 
    f_short = Kanaele
 
    Put #a,,f_short
 
 
    f_lang = Samplerate
 
    Put #a,,f_lang
 
    f_lang = BytesProSekunde
 
    Put #a,,f_lang
 
 
    f_short = Blockgroesse
 
    Put #a,,f_short
 
    f_short = Bittiefe
 
    Put #a,,f_short
 
 
    f_char = asc("d")
 
    Put #a,,f_char
 
    f_char = asc("a")
 
    Put #a,,f_char
 
    f_char = asc("t")
 
    Put #a,,f_char
 
    f_char = asc("a")
 
    Put #a,,f_char
 
 
    f_lang = Kanaele*Laenge*Bittiefe/8
 
    Put #a,,f_lang
 
    
 
    return a
 
end function  | 	             | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Jojo alter Rang
  
  Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
  | 
		
			
				 Verfasst am: 16.03.2010, 21:39    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Naja, es ginge sicher auch einfacher, wenn du dich nicht auf die genaue Frequenz verlassen willst, sondern einfach die Länge einer Sägezahnschwingung spezifizieren würdest, also sowas in der art:
 
 
 	  | Code: | 	 		  
 
dim as double wert
 
wert = ((x mod 200) / 200) - 0.5
 
wert += ((x mod 800) / 800) - 0.5
 
 | 	  
 
 
Weiß nicht, ob dir das weiterhilft, aber es ist eine Möglichkeit. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		S_F
 
 
  Anmeldungsdatum: 16.03.2010 Beiträge: 6
 
  | 
		
			
				 Verfasst am: 16.03.2010, 21:50    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Sorry, hilft mir leider nicht weiter
 
Ich müsste im fall "x mod a" das a stufenlos verändern können. Eine feste Länge für die Schwingung festzulegen würde das ganze zu unflexibel machen.
 
 
 	  | Code: | 	 		  
 
wert = saegezahn(440 + sin(t)*20 , 0.8 , t)
 
  | 	  
 
 
Dieses Beispiel zeigt eine Anwendung bei der der Ton um 20Hz rauf und runter schwankt. Damit dies Funktioniert muss saegezahn() natürlich für beliebige Werte funktionieren.
 
 
Gibt es kein mod für Fliesskommazahlen? | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Jojo alter Rang
  
  Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
  | 
		
			
				 Verfasst am: 16.03.2010, 21:56    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Überlege dir mal, was "Teilen mit Rest" bedeutet, um die Antwort zu bekommen.
 
Eine Möglichkeit wäre z.B., alle Zahlen *100 zu nehmen, um die Genauigkeit bei MOD zu erhöhen. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		S_F
 
 
  Anmeldungsdatum: 16.03.2010 Beiträge: 6
 
  | 
		
			
				 Verfasst am: 16.03.2010, 22:04    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Ich glaube ich bin der Lösung langsam auf der Spur.
 
Für meine Zwecke könnte man mod "Entfremden", in etwa so dass er folgendes rechnet
 
 
 	  | Code: | 	 		  
 
3.2 / 1.2 = 2 Rest 0.8
 
3.2 mod 0.8 = 0.8
 
 | 	  
 
 
Man müsste selbstverständlich einen neuen Namen erfinden. Vielleicht kmod für Kommamodulo.
 
 
Jedenfalls Danke @Jojo. Ich hätte das Problem mit mod und Ganzzahlen wohl nie herausgefunden.
 
 
Edit:
 
 
 	  | Code: | 	 		  Function kmod(a as double, b as double) as double
 
    dim as double wert = a / b
 
    kmod = a - cint(a / b - 0.5)*b
 
end function | 	  
 
 
Für alle die einmal kmod berechnen wollen. | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		28398
 
 
  Anmeldungsdatum: 25.04.2008 Beiträge: 1917
 
  | 
		
			
				 Verfasst am: 16.03.2010, 22:29    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				a mod b = a - ((a \ b) * b)
 
 
Habs jetzt nicht nachgerechnet, sollte aber stimmen.
  Zuletzt bearbeitet von 28398 am 16.03.2010, 23:04, insgesamt 2-mal bearbeitet | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		S_F
 
 
  Anmeldungsdatum: 16.03.2010 Beiträge: 6
 
  | 
		
			
				 Verfasst am: 16.03.2010, 22:34    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				| Da blicke ich jetzt nicht durch. Für was steht m? | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		28398
 
 
  Anmeldungsdatum: 25.04.2008 Beiträge: 1917
 
  | 
		
			
				 Verfasst am: 16.03.2010, 22:59    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Vertippt  
 
Ist jetzt richtig. | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		S_F
 
 
  Anmeldungsdatum: 16.03.2010 Beiträge: 6
 
  | 
		
			
				 Verfasst am: 16.03.2010, 23:03    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				lol, für mich ist es immer noch unlogisch
 
 
a mod b = a - b*(a/b) = a - a = 0 | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		28398
 
 
  Anmeldungsdatum: 25.04.2008 Beiträge: 1917
 
  | 
		
			
				 Verfasst am: 16.03.2010, 23:05    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				| Ja ist mir gerade aufgefallen. JETZT _sollte_ es aber wirklich stimmen | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		bubu
 
 
  Anmeldungsdatum: 21.02.2010 Beiträge: 13
 
  | 
		
			
				 Verfasst am: 18.05.2010, 16:01    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Ich habe zu  diesem Programm noch eine Frage: wie kann ich mit dem auch andere Töne (dreieck, rechteck etc.) erzeugen und diese mit Voltas D_Sound wieder abspielen (komme da einfach nicht weiter)? Wäre wichtig für eine kleine Drum Machine, die ich euch natürlich auch vorstellen werde. Vielen Dank.   
 
 
Hier noch der Code:
 
 	  | Code: | 	 		  
 
 
#Include once "Wave.inc"
 
dim shared as HWND V_hwnd
 
dim shared as string title
 
v_hwnd=FindWindow(0, title)
 
if V_DSinit(V_hwnd)<>0 then end
 
V_DSLoadSound (1, "Wave.wav",19)
 
DIM SHARED AS INTEGER Samplerate=44100
 
DIM SHARED AS INTEGER Bittiefe=32 
 
DIM SHARED AS INTEGER Kanaele=2
 
DIM SHARED AS INTEGER laenge=2^12 
 
DIM  AS DOUBLE Array(0 TO laenge-1) 
 
DIM AS INTEGER t,a,sampel
 
DIM AS DOUBLE sampel2
 
DECLARE FUNCTION new_wave(nam AS STRING) AS INTEGER 
 
DECLARE FUNCTION saegezahn(frequenz AS DOUBLE,amplitude AS DOUBLE,t AS DOUBLE) AS DOUBLE 
 
FOR t=1 TO laenge 
 
Array(t-1)=saegezahn(256,0.8,t) 
 
NEXT 
 
a=new_wave("Wave")
 
FOR t=0 TO laenge-1 
 
sampel2=Array(t) * 2^31
 
sampel=sampel2 
 
PUT #a,,sampel 
 
NEXT 
 
FUNCTION saegezahn(frequenz AS DOUBLE,amplitude AS DOUBLE,t AS DOUBLE) AS DOUBLE 
 
saegezahn = (((t MOD (Samplerate/Frequenz)) / (Samplerate/Frequenz))-0.5) * Amplitude 
 
END FUNCTION 
 
FUNCTION new_wave(nam AS STRING) AS INTEGER 
 
DIM AS INTEGER a=FREEFILE 
 
OPEN nam + ".wav" FOR BINARY AS #a 
 
DIM f_lang AS INTEGER 
 
DIM f_short AS SHORT 
 
DIM AS INTEGER Blockgroesse = Kanaele * Bittiefe/8 
 
DIM AS INTEGER BytesProSekunde = Blockgroesse * Samplerate 
 
DIM f_Char AS BYTE 
 
f_char = ASC("R") 
 
PUT #a,,f_char 
 
f_char = ASC("I") 
 
PUT #a,,f_char 
 
f_char = ASC("F") 
 
PUT #a,,f_char 
 
f_char = ASC("F") 
 
PUT #a,,f_char 
 
f_lang = 36+Kanaele*Laenge*Bittiefe/8 
 
PUT #a,,f_lang 
 
f_char = ASC("W") 
 
PUT #a,,f_char 
 
f_char = ASC("A") 
 
PUT #a,,f_char 
 
f_char = ASC("V") 
 
PUT #a,,f_char 
 
f_char = ASC("E") 
 
PUT #a,,f_char 
 
f_char = ASC("f") 
 
PUT #a,,f_char 
 
f_char = ASC("m") 
 
PUT #a,,f_char 
 
f_char = ASC("t") 
 
PUT #a,,f_char 
 
f_char = ASC(" ") 
 
PUT #a,,f_char 
 
f_lang = 16 
 
PUT #a,,f_lang 
 
f_short = 1 
 
PUT #a,,f_short 
 
f_short = Kanaele 
 
PUT #a,,f_short 
 
f_lang = Samplerate 
 
PUT #a,,f_lang 
 
f_lang = BytesProSekunde 
 
PUT #a,,f_lang 
 
f_short = Blockgroesse 
 
PUT #a,,f_short 
 
f_short = Bittiefe 
 
PUT #a,,f_short 
 
f_char = ASC("d") 
 
PUT #a,,f_char 
 
f_char = ASC("a") 
 
PUT #a,,f_char 
 
f_char = ASC("t") 
 
PUT #a,,f_char 
 
f_char = ASC("a") 
 
PUT #a,,f_char 
 
f_lang = Kanaele*Laenge*Bittiefe/8 
 
PUT #a,,f_lang 
 
RETURN a 
 
END FUNCTION
 
V_DSPlay_one(1,19)
 
sleep 2000,1
 
V_DSExit:end | 	 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Jojo alter Rang
  
  Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
  | 
		
			
				 Verfasst am: 18.05.2010, 17:01    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				RIFF WAVE-Header vor die Daten packen. _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		bubu
 
 
  Anmeldungsdatum: 21.02.2010 Beiträge: 13
 
  | 
		
			
				 Verfasst am: 18.05.2010, 17:22    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Danke für deine Antwort; doch funktioniert es jetzt auch so.   | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		volta
 
 
  Anmeldungsdatum: 04.05.2005 Beiträge: 1876 Wohnort: D59192
  | 
		 | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		ThePuppetMaster
 
  
  Anmeldungsdatum: 18.02.2007 Beiträge: 1839 Wohnort: [JN58JR]
  | 
		
			
				 Verfasst am: 19.05.2010, 08:04    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				@S_F
 
 
 	  | Code: | 	 		  
 
'...
 
f_char = ASC("W")
 
PUT #a,,f_char
 
f_char = ASC("A")
 
PUT #a,,f_char
 
f_char = ASC("V")
 
PUT #a,,f_char
 
f_char = ASC("E")
 
PUT #a,,f_char
 
f_char = ASC("f")
 
PUT #a,,f_char
 
f_char = ASC("m")
 
PUT #a,,f_char
 
f_char = ASC("t")
 
PUT #a,,f_char
 
f_char = ASC(" ")
 
PUT #a,,f_char 
 
'...
 
 | 	  
 
 
sowas kannst du übrigens auch so schreiben,
 
 
 	  | Code: | 	 		  
 
Dim T as String = "WAVEfmt "
 
For X as UInteger = 1 to Len(T)
 
    PUT #a, , T[X - 1]
 
Next
 
 | 	  
 
 
und sowas hier
 
 	  | Code: | 	 		  
 
f_lang = 4+24+8+Kanaele*Laenge*Bittiefe/8
 
PUT #a,,f_lang
 
 | 	  
 
 
kann man auch so machen:
 
 	  | Code: | 	 		  
 
PUT #a,,CUInt(4+24+8+Kanaele*Laenge*Bittiefe/8)
 
 | 	  
 
 
Das ganze gibts auch für die anderen DatenTypen: CUInt, CInt, CByte, CUByte, ...
 
 
 
MfG
 
TPM _________________ [ WebFBC ][ OPS ][ ToOFlo ][ Wiemann.TV ] | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		Jojo alter Rang
  
  Anmeldungsdatum: 12.02.2005 Beiträge: 9736 Wohnort: Neben der Festplatte
  | 
		
			
				 Verfasst am: 19.05.2010, 18:42    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Warum nicht einfach ein UDT verwenden? _________________ » Die Mathematik wurde geschaffen, um Probleme zu lösen, die es nicht gäbe, wenn die Mathematik nicht erschaffen worden wäre.
 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		28398
 
 
  Anmeldungsdatum: 25.04.2008 Beiträge: 1917
 
  | 
		
			
				 Verfasst am: 19.05.2010, 19:16    Titel:  | 
				     | 
			 
			
				
  | 
			 
			
				Warum nicht einfach
 
 	  | Code: | 	 		  | PUT #a, , "WAVEfmt " | 	 
  | 
			 
		  | 
	 
	
		| Nach oben | 
		 | 
	 
	
		  | 
	 
	
		 | 
	 
 
  
	 
	    
	   | 
	
Du kannst keine Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum nicht antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen.
  | 
   
 
     |