 |
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, 22: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, 22: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, 22: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, 22: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, 22: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, 22: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, 23: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, 23:29 Titel: |
|
|
a mod b = a - ((a \ b) * b)
Habs jetzt nicht nachgerechnet, sollte aber stimmen.
Zuletzt bearbeitet von 28398 am 17.03.2010, 00:04, insgesamt 2-mal bearbeitet |
|
Nach oben |
|
 |
S_F
Anmeldungsdatum: 16.03.2010 Beiträge: 6
|
Verfasst am: 16.03.2010, 23: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, 23:59 Titel: |
|
|
Vertippt
Ist jetzt richtig. |
|
Nach oben |
|
 |
S_F
Anmeldungsdatum: 16.03.2010 Beiträge: 6
|
Verfasst am: 17.03.2010, 00: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: 17.03.2010, 00: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, 17: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, 18: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, 18: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, 09: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, 19: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, 20: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.
|
|