Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Sägezahnschwingung

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
S_F



Anmeldungsdatum: 16.03.2010
Beiträge: 6

BeitragVerfasst am: 16.03.2010, 22:09    Titel: Sägezahnschwingung Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
Jojo
alter Rang


Anmeldungsdatum: 12.02.2005
Beiträge: 9736
Wohnort: Neben der Festplatte

BeitragVerfasst am: 16.03.2010, 22:13    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
S_F



Anmeldungsdatum: 16.03.2010
Beiträge: 6

BeitragVerfasst am: 16.03.2010, 22:31    Titel: Antworten mit Zitat

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!'mit dem Kopf durch die Mauer wollen'

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
mit dem Kopf durch die Mauer wollen mit dem Kopf durch die Mauer wollen mit dem Kopf durch die Mauer wollen mit dem Kopf durch die Mauer wollen
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Jojo
alter Rang


Anmeldungsdatum: 12.02.2005
Beiträge: 9736
Wohnort: Neben der Festplatte

BeitragVerfasst am: 16.03.2010, 22:39    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
S_F



Anmeldungsdatum: 16.03.2010
Beiträge: 6

BeitragVerfasst am: 16.03.2010, 22:50    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
Jojo
alter Rang


Anmeldungsdatum: 12.02.2005
Beiträge: 9736
Wohnort: Neben der Festplatte

BeitragVerfasst am: 16.03.2010, 22:56    Titel: Antworten mit Zitat

Ü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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
S_F



Anmeldungsdatum: 16.03.2010
Beiträge: 6

BeitragVerfasst am: 16.03.2010, 23:04    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
28398



Anmeldungsdatum: 25.04.2008
Beiträge: 1917

BeitragVerfasst am: 16.03.2010, 23:29    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden
S_F



Anmeldungsdatum: 16.03.2010
Beiträge: 6

BeitragVerfasst am: 16.03.2010, 23:34    Titel: Antworten mit Zitat

Da blicke ich jetzt nicht durch. Für was steht m?
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
28398



Anmeldungsdatum: 25.04.2008
Beiträge: 1917

BeitragVerfasst am: 16.03.2010, 23:59    Titel: Antworten mit Zitat

Vertippt zwinkern
Ist jetzt richtig.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
S_F



Anmeldungsdatum: 16.03.2010
Beiträge: 6

BeitragVerfasst am: 17.03.2010, 00:03    Titel: Antworten mit Zitat

lol, für mich ist es immer noch unlogisch

a mod b = a - b*(a/b) = a - a = 0
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
28398



Anmeldungsdatum: 25.04.2008
Beiträge: 1917

BeitragVerfasst am: 17.03.2010, 00:05    Titel: Antworten mit Zitat

Ja ist mir gerade aufgefallen. JETZT _sollte_ es aber wirklich stimmen
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
bubu



Anmeldungsdatum: 21.02.2010
Beiträge: 13

BeitragVerfasst am: 18.05.2010, 17:01    Titel: Antworten mit Zitat

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

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
Benutzer-Profile anzeigen Private Nachricht senden
Jojo
alter Rang


Anmeldungsdatum: 12.02.2005
Beiträge: 9736
Wohnort: Neben der Festplatte

BeitragVerfasst am: 18.05.2010, 18:01    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
bubu



Anmeldungsdatum: 21.02.2010
Beiträge: 13

BeitragVerfasst am: 18.05.2010, 18:22    Titel: Antworten mit Zitat

Danke für deine Antwort; doch funktioniert es jetzt auch so. happy
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
volta



Anmeldungsdatum: 04.05.2005
Beiträge: 1876
Wohnort: D59192

BeitragVerfasst am: 18.05.2010, 18:28    Titel: Antworten mit Zitat

Hi,
ist zwar Delphi aber gut erklärt: http://wiki.delphigl.com/index.php/Tutorial_Software-Synthesizer
_________________
Warnung an Choleriker:
Dieser Beitrag kann Spuren von Ironie & Sarkasmus enthalten.
Zu Risiken & Nebenwirkungen fragen Sie Ihren Therapeuten oder Psychiater.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
ThePuppetMaster



Anmeldungsdatum: 18.02.2007
Beiträge: 1839
Wohnort: [JN58JR]

BeitragVerfasst am: 19.05.2010, 09:04    Titel: Antworten mit Zitat

@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
Benutzer-Profile anzeigen Private Nachricht senden
Jojo
alter Rang


Anmeldungsdatum: 12.02.2005
Beiträge: 9736
Wohnort: Neben der Festplatte

BeitragVerfasst am: 19.05.2010, 19:42    Titel: Antworten mit Zitat

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
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
28398



Anmeldungsdatum: 25.04.2008
Beiträge: 1917

BeitragVerfasst am: 19.05.2010, 20:16    Titel: Antworten mit Zitat

Warum nicht einfach
Code:
PUT #a, , "WAVEfmt "
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
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.

 Impressum :: Datenschutz