Grundlegendes

Übersicht Ressourcen Sound & Music

Neue Antwort erstellen

Vertex

Betreff: Grundlegendes

BeitragFr, Sep 10, 2004 12:51
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi!
Es geht mir hier um das grundlegende Verständnis in Sachen Synthesizer...

Frequenz und Samples
Was wird nun als Sample bezeichnet? Im Ton die einzelnen Daten oder der Ton selber? Gehen wir davon aus, ich habe einen Ton der 100 Byte groß ist, und jede Datei(singular von Daten?) ist ein Byte groß. So das ich 100 Daten für diesen Ton habe. Ein Byte kann 0 - 255 annehmen. Wird das ganze dann so im Lautsprecher angesteuert, das 255 volle Stromstärke ist, und 0 garkeine? Was besagt die Frequenz eines Tons? Bei 1000Hz wird der Ton dann 1000 mal in der Sekunde abgespielt?


Lowpass, Highpass und Bandsperre
Bleiben wir bei den 100 Byte und 1 Byte pro Datei. Funktioniert dann ein Lowpassfilter so, das ich meinetwegen einen bestimmten Wert (von 0 - 255) sagen wir 50 angebe, und alle Daten die unter 50 sind einfach auf 0 gesetzt werden? Das selbe für Highpass und Bandsperre wo die Daten innerhalb eines Wertebereiches auf 0 gesetzt werden.

Ringmodulation
Zitat:
Das Ringmodulation bildet Summe und Differenz der an den Eingängen anliegenden Frequenzen (z.B. 3000 Hz an Eingang A und 400 Hz an Eingang B ergeben am Ausgang 2600 Hz und 3400 Hz).

Warum Frequnzen, und warum kann der Ausgang 2 Frequnzen beinhalten?

mfg olli
vertex.dreamfall.at | GitHub

BladeRunner

Moderator

BeitragSa, Sep 11, 2004 9:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Achtung Halbwissen aus grauer Vorzeit
Wink

Sample ist die komplette Sammlung aller Daten. Ein einzelnes Datum (Einzahl von Daten Wink ) ergibt noch keinen Sound. Je nach format besteht ein einzelnes dieser Daten jedoch aus mehr als einem Byte: bei 16-Bit Stereo @ 44100Hz zB hast du dann 2Byte pro Kanal (da Stereo -> 4 Byte), dies mal 44100 hz -> 176400 Bytes / Sekunde unkomprimiertes Wav.
Grundsätzlich musst du jedoch zwischen der Frequenz deiner .wav und der "gehörten" Frequenz unterscheiden. Die 44100hz sind CD-Qualität, d.h. auf einer CD sind alle Stücke in diese 44100 Häppchen pro Sekunde zerlegt gespeichert. Wenn Du nun zB einen anggezogenen Kammerton A hast (Frequenz 440hz), dann sind die Daten seiner Hüllkurve pro Sekunde 100,22 mal gespeichert (44100/440).
Dies liegt daran dass sich ein Klang nicht aus einem einzelnen Lautstärkewert ergibt, sondern aus dem Verlauf seiner Schwingung ( -> seiner Hüllkurve). Hättest du ein .wav welches ständig Vollausschlag hat, würdest du nichts hören, da der Lautsprecher nicht schwingen würde.

Lowpass/Highpass/Bandsperre

Funktionieren üblicherweise in einem bestimmten Frequenzband, d.h. du müsstest die Frequenzen der einzelnen Schwingungen deines Samples kennen (bei einzelnen Tönen einfach, bei komplexen Soundshemata nahezu unmöglich). Ein Lowpass würde dann die Amplitude aller unterhalb des Grenzwert liegenden Sounds reduzieren. Hie ist mein Wissen sehr verstaubt, mag sein dass ich mich täusche.

Ringmodulation
Eine Ringmodulation ist (wenn ich das richtig verstanden habe) eine Möglichkeit 2 Sounds in ihrer Tonhöhe (=Frequenz) zu Beeinflussen, d.h. die Beiden sounds Verändern sich abhängig voneinander Eingang A-> Ausgang A ; Eingang B -> Ausgang B.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Vertex

BeitragSa, Sep 11, 2004 15:57
Antworten mit Zitat
Benutzer-Profile anzeigen
Danke Dir!
Bei mir ist es so, ich habe 4 Wellenformen zur Auswahl(Dreieck, Sägezahn, Rechteck und Rauschen) und ich weiss auch die Frequenz sowie die Hüllkurve. Das ganze 8 Bit mono (wer ihn kennt, SID MOS Chip - der Soundchip vom C64). Jetzt steht in der Anleitung z.B. beim Lowpass:
Zitat:
LP (Bit 4): Wenn dieses Bit gesetzt ist, ist der Tiefpass eingeschaltet, d. h. alle
Frequenzen unterhalb der Eckfrequenz bleiben unverändert, alle Frequnzen ober-
halb werden mit 12 dB/Oktave abgeschwächt. Es entstehen volle Klänge.

Es muss dazu gesagt werden, das der SID 3 Tongeneartoren hat, und der Lowpassfilter auf alle 3 Tongeneratoren angewendet wird.

Was bedeutet das nun konkret? Ich betreibe ja z.B. die Dreieckskurve mit 1000 Hz. Also die Daten innerhalb des Samples steigen von 0 bis 255 an. Dieser Sample würde dann 1000 mal in der Sekunde abgespielt werden. Stelle ich nun die Eckfrequenz auf 500 Hz, würde ich den Tongenerator praktisch nichtmehr hören, da er ja mit 1000 Hz über 500 Hz liegt? Was ist eigentlich die Oktave? Laut Wikipedia das 1/2 Verhältnis zu einer Frequenz. Würde das heißen, dass bei 750 Hz von den Wertebereich der Daten 12 abgezogen werden müssten? Und bei dem Beispiel hier oben mit 1000 Hz 24?

Zur Rindmodulation muss ich mich nochmal erkundigen beim SID.
mfg olli
vertex.dreamfall.at | GitHub

BladeRunner

Moderator

BeitragSa, Sep 11, 2004 16:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Der SID, ja ... das waren noch Sounds.... (daher hab ich übrigens mein angestaubtes Wissen Wink )

Der dB-Wert der verringert wird entspricht einer Amplitudenverringerung,
d.h. alle Sounds die über deinen 500 Hz Eckfrequenz liegen werden in ihrer Amplitude verringert (Bsp: bei voller Lautstärke wird das Dreieck von 0-255 hochgezählt, bei halber von 0-127).
Wenn ich nit irre (was aber schon sein kann ... lang ists her) müssten 12 dB einem 16tel der Ursprungslautstärke entsprechen (da alle 3dB-> Verdopplung der Lautstärke).
d.h. jede über dem eckwert liegende Oktave wird um ein weiteres 16.el abgeschwächt.
(da eine Oktave immer bei Doppelter Frequenz ist also: 500-999Hz -12 dB, 1000-1999 Hz -24dB etc...)
Bei einem Wert von 255 müsstest du also bei 12dB Absenkung (256/16)=16 von der Amplitude abziehen und so fort.

EDIT: Darf man fragen was du mit der guten alten Soundnudel machen willst? (Einen BB-SID-Emu vielleicht? Daran hatt ich auch schon mal gedacht, wär ein interessantes Projekt...)
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Vertex

BeitragSa, Sep 11, 2004 17:04
Antworten mit Zitat
Benutzer-Profile anzeigen
Und ich danke nochmal! Ja das dürfte ein 16. von 256 sein, da man im low Nibble vom Register 24 die Gesamtlautstärke einstellen kann(Nibble = 1/2 Byte -> 4 Bit -> 2^4 = 16 Möglichkeiten). Ansonsten ja, ich versuche einen SID Emulator zu bauen. Ich will ersteinmal versuchen, den Chip zu emulieren, und dann via *.sid Datei versuchen die alten Musikwerke abzuspielen.
mfg olli
vertex.dreamfall.at | GitHub

BladeRunner

Moderator

BeitragSa, Sep 11, 2004 17:32
Antworten mit Zitat
Benutzer-Profile anzeigen
Da Hauptproblem dabei dürfte sein dass der SID ein teilweise analoges Bauteil war- die Simulation gestaltet sich also etwas schwierig. Das Projekt hat mein absolutes Interesse. Wenn ich dir im Rahmen meiner begrenzten Möglichkeiten helfen kann melde dich einfach bei mir. Vielleicht kann ich noch ein paar alte Erinnerungen (und Anleitungen *hrhr*) ausgraben...
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Phalastos

BeitragSa, Sep 11, 2004 19:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Da gibt es schon massig Lösungen. ( HardSID , VSt Plugin etc )
Forbiddenmagic - Warfare of Forgotten Power

BladeRunner

Moderator

BeitragSa, Sep 11, 2004 19:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Sicher, aber es geht ja um eine "bb-interne" Lösung (und um den Fun sich darüber die Birne weichzudenken).
Durch die eingeschränkten BB-Befehle soundseits denke ich jedoch dass eine Realtimelösung bb-seits schwierig (bis unmöglich) wird. Nichtsdestotrotz ein interessantes Projekt.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Vertex

BeitragSa, Sep 11, 2004 19:49
Antworten mit Zitat
Benutzer-Profile anzeigen
Das ganze läuft über BASS.dll ab, wo ich die Daten direkt in ein Sample schreiben kann. Aber mit Blitz selber würde es nur so gehen, das man eine WAV Datei erstellt und diese abspielt.
mfg olli
vertex.dreamfall.at | GitHub

Vertex

BeitragSa, Sep 11, 2004 23:24
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich komme schon beim Oszillator nicht ganz klar...
Wenn ich den Kammerton A ausgeben will als Rechteckkurve kommt bei mir nur eine Art Herzschlag heraus. Wie wieviel Byte müssen die Samples eigentlich sein? Ich habe es mit 255 Byte versucht, und einer Pulsweite von 128. Also von 0 bis 127 alle Daten auf 255 und von 128 bis 255 alle Daten auf 0. Und da kam eben dieser Herzschlageffekt heraus, laut Beschreibung sollte aber dieses Pulsweitenverhältnis ein Zumpfinstrument sehr nahe kommen oO
mfg olli
vertex.dreamfall.at | GitHub

BladeRunner

Moderator

BeitragSo, Sep 12, 2004 0:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Kammerton a bei 44100 hz für eine Sekunde im Rechteck:
44100 bytes, wobei:
-alle 100(,22) bytes (abgerundet) eine komplette Kurve kommt (44100/440), d.h. 50 Bytes mit $00 und 50 Bytes mit $ff.

Die Pulsweite ist übrigens ein Sonderfall bei der SquareWave und beschreibt das Verhältnis von Max zu Min-Dauer, d.h. wie lange innerhalb einer Schwingung Max und Minpegel anliegen. Beim C64 gab es dafür 12bit (also 4096 Kombinationen, wobei man gegen 0 und 4096 quasi nichts mehr vom Sound hörte da ja keine echte Schwingung mehr auftrat). Bei 2049 hatte man eine komplett ausgeglichene Schwingung, dass ist auch der Fall den ich oben beschrieben habe.

Ansonsten wird der Sound jetzt noch nicht allzuviel hergeben, da du ja ausser der Schwingungsform noch keinerlei Klangcharakteristik per Hüllkurvenprogrammierung reingebracht hast (per ADSR).

Was du gemacht hast (gesetzt den Fall du hast ein 44100Hz Sample erstellt) entspricht einem Lautsprecherknacken von 1/172 Sekunde Dauer.

Hoffe es hilft, und halt mich bitte weiter auf dem Laufenden.

PS: Ich könnte mir vorstellen (je nachdem wie rechenintensiv es wird) dass man eventuell die generierten Sounds in Mini-.wavs von Sekundenbruchteilen Dauer zerlegen könnte um somit ein "realtime"-verändern der Sounds auch ohne bass-dll zu verwirklichen.
Aber erstmal sollte das Ganze laufen...
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Vertex

BeitragSo, Sep 12, 2004 0:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Hmm ich verstehe das immer noch nicht ganz...
Was gibt die Frequenz beim SID jetzt an? Sagen wir mal eine Frequnz von 100 Hz und Dreieckskurve ist eingestellt. Wie oft läuft die Schleife von 0 bis 255 in der Sekunde jetzt ab? 100 mal?
mfg olli
vertex.dreamfall.at | GitHub

BladeRunner

Moderator

BeitragSo, Sep 12, 2004 2:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Beim Dreieck mit 100 Hz wird das komplette Dreieck 100 mal in der Sekunde durchlaufen, also 0,1,2,3,...254,255,254,...,2,1 = eine Schwingung.
Was das verwirrende bei BB (bzw. auf dem PC) darstellt ist der Fakt dass du die Sounddaten ja quasi als Sample vorliegen haben musst. Nun wird ein 100hz-wav nicht Funktionieren (das macht der Codec/ die Soundcard / wasweissich nicht mit)- daher ist es günstig alle Sounds in einer vordefinierten Wiederholrate zu "samplen".
Also 44100 Hz Wiederholfrequenz ABER 100 hz Tonhöhe. (was dann 44100/100 = 100 Wiederholungen à 441 Byte für eine Sekunde Laufzeit wären).
Du kannst bei C64-Sounds auch bedenkenlos Wiederholraten von 22050Hz oder gar 11000 Hz nehmen - der SID hat bei gesampleten Daten nicht mehr als 8.5kHz Wiederholrate geschafft, da hast du also locker Platz.
Wichtig ist nur der besagte Unterschied Wiederholrate zu Tonhöhe, um eine Bestimmte Tonhöhe bei einer bestimmten Wiederholrate zu erreichen muss eben per Division die Anzahl Bytes für eine Schwingung ermittelt werden.
Beim C64 wurde die Tonlänge nicht durch eine Wiederholrate angegeben (was auch den Unterschied zum PC und daher wohl deine Verständnisschwierigkeiten macht) sondern die ADR Zeiten waren über Register in festen Schritten einzustellen und die S(ustain) ging eben solange der Tongenerator eingeschaltet war.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Vertex

BeitragMo, Sep 13, 2004 17:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich habe mal jetzt alles zusammengefasst, was ich durch dich und andere Quellen so erfasst habe:
The SID Project


    Kenntnisse
    - Der SID ist Mono, und hat eine Auflösung von 8 Bit (Amplitude geht von 0 bis 255)
    - Die angegebene Frequenz ist nicht die Samplingrate. Das heißt, dass z.B. bei der Sägezahnwelle bei einer Frequenz von 440 der Oszillator von 0 bis 255 440 mal in der Sekunde zählt.
    - Die Pulsbreite gibt das Tastverhältnis von 0% bis 100% an. Die Auflösung ist 4096. Bei einer Abtastrate von 70% ist das Verhältnis von Highpegel(255) zu Lowpegel(0) 7 zu 3. Ist die Abtastrate auf 50% eingestellt, so ergibt das einen sinusähnlichen Klang.
    - Beim Filter bedeutet 12 dB / Oktave, dass ein 16.tel der Ursprungslautstärke pro Oktave(die doppelte Eckfrequenz) abgezogen wird.
    - Das Hard Sync bedeutet, wenn der eine Oszillator seine Welle durchlaufen hat, zwingt er den zweiten zum Neustart.
    - Das Rauschen ist ein sogenanntes weißes Rauschen(gleiche Amplitudenverteilung unabhängig von der Frequenz)


Was noch gebarucht wird ist, wie sich die Ringmodulation verhällt. Event. ist es so, das dem Oszi 1 der Durchschnitt aus der Differenz von Oszi 2 und 3 und der Summe aus Oszi 2 und 3 zugewiesen wird. Und dann noch, wie lange eine Periode bei der Rechteckwelle sowie beim Rauschen ist. Bei einer Sägezahnwelle geht sie ja von 0 bis 256, bei einer Dreieckswelle von 0 bis 255 und dann von 254 bis zu 1 ?oder
mfg olli
vertex.dreamfall.at | GitHub

BladeRunner

Moderator

BeitragMo, Sep 13, 2004 22:16
Antworten mit Zitat
Benutzer-Profile anzeigen
Zitat:
Das heißt, dass z.B. bei der Sägezahnwelle bei einer Frequenz von 440 der Oszillator von 0 bis 255 440 mal in der Sekunde zählt

Die 255 nicht unbedingt, da die Lautstärke über die Amplitude geregelt wird, d.h. 255 entspricht voller Lautstärke, bei 127 hättest du halbe usw.

Auch das ist jedoch eigentlich nicht ganz korrekt, da der SID in der lage ist, Volumes >100% zu liefern, d.h. die 100% liegen niedriger als 255.

Zitat:
Und dann noch, wie lange eine Periode bei der Rechteckwelle sowie beim Rauschen ist.

Eine Periode bei der Rechteckwelle ist ein mal max und ein mal min. Also 440hz Rechteck bei maximaler Lautstärke: 440 mal 255 und 440 mal 0.
Beim Rauschen bin ich überfragt, werd mich jedoch in meine alte 64er Lektüre reingraben. Ich hatte auch in Erinnerung das der SID rosa Rauschen produziert- kanbn mich hier aber irren.
Wenn es weisses Rauschen gemäß deiner Definition ist (gleiche Amplitudenverteilung unabhängig von der Frequenz) spielt eine Periodenlänge keine wirkliche Rolle- es gibt eh keine erkennbare Tonhöhe, weshalb auch die Periode irrelevant ist.

Zitat:
Bei einer Sägezahnwelle geht sie ja von 0 bis 256, bei einer Dreieckswelle von 0 bis 255 und dann von 254 bis zu 1

Jain. Siehe oben: die werteskala ist abhängig von der gewählten Lautstärke. Die Werteverteilung ist aber korrekt so, also:
/\/\ -Dreieck (linear zw. min und Max steigend und fallend, ähnlich wie Sinus)
/|/| - Sägezahn -linear steigend von min zu max, dann abrupt zurück auf min.
--_--_ -Rechteck abrupt wechselnd zw. 2 Werten, Wechsel im Pulsweitenverhältnis. (min und max)

Ich denke man kann getrost bei allen Fällen "0" als minimum annehmen, Max ist die jeweilig gewünschte Lautstärke.

PS: Hat das modifizierte Beispiel funktioniert? Und könntest du mir Angaben zu der 2ten benutzten dll (mit dem rtlmove...) geben? (Gern auch per PM)

Hab diese Woche Spätschicht wie meine Freundin, werd daher eher selten am Rechner sein, melde mich aber sobald ich kann mit weiteren Einzelheiten.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

BladeRunner

Moderator

BeitragMi, Sep 15, 2004 10:34
Antworten mit Zitat
Benutzer-Profile anzeigen
UPDATE:
Nur ein kurzes Update, sobald ich frei hab kommt mehr. Ich hab mal in meinen alten Unterlagen gewühlt und zum einen mein C64 Bedienerhandbuch als auch mein 64 Intern (ein 1000-Seiten-Wälzer)aufgetrieben; das grosse 64er Buch (>1500 Seiten voll Detailwissen) liegt sicher auch noch wo, da muss ich aber noch ein bisserl suchen.

Werde die nächsten Tage das in diesen Büchern geschriebene zusammenfassen und dann on stellen.
Vorweg:
Das Zählen von 0 bis 255: Der SID zählt intern bei seinen Registern wirklich immer bis 255, egal welche Lautstärke eingestellt war. die geringeren Werte die ich angegeben habe gelten für das von BB erzeugte .wav-File. Hier gilt selbstredend auch dass eine genauere Erklärung mit dem nächsten Update folgt.

Zu Ringmodulation etc. werd ich sicher auch angaben machen können.
Ich hab ja meinen guten alten Brotkasten noch aufgebaut- ich werde bezüglich der Register noch einige Tests am Original ausführen (wenn ich das verf... Kabel finde könnte ich die sogar aufnehmen/samplen).
So long...
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92

Vertex

BeitragSa, Sep 18, 2004 0:48
Antworten mit Zitat
Benutzer-Profile anzeigen
Hier mal der Ansatz des C64 CPU Emulators:
main.bb:
Code: [AUSKLAPPEN]
; ----------------------------------------------------------------------------

Include "cpu.bb" ; 6510 CPU Emulator
Include "sid.bb" ; 6585 SID Emulator

; file information
Global fName$, fSize, fStream

; header information
Global hSignature$, hVersion, hDataOffset, hLoadAddr, hInitAddr
Global hPlayAddr, hSongs, hStartSong, hSpeed, hName$, hAuthor$
Global hCopyright$, hFlags

; ----------------------------------------------------------------------------

fName$ = CommandLine$()
fSize = FileSize(fName$)

fStream = ReadFile(fName$)
If fStream = False Then
   RuntimeError "Can't open file!"
EndIf

loadHeader
checkHeader

cpuMem = CreateBank(fSize-hDataOffset+hLoadAddr)
DebugLog ReadBytes(cpuMem, fStream, hLoadAddr, fSize-hDataOffset)
CloseFile fStream

cpuInit
DebugLog fSize-hDataOffset
DebugLog PeekByte(cpuMem, cpuPC+10)
;sidInit


; ----------------------------------------------------------------------------

Function loadHeader()
   Local i, tmp
   
   For i = 0 To 3
      hSignature$ = hSignature$+Chr$(ReadByte(fStream))
   Next
   hVersion    = b2l(ReadShort(fStream))
   hDataOffset = b2l(ReadShort(fStream))
   hLoadAddr   = b2l(ReadShort(fStream))
   hInitAddr   = b2l(ReadShort(fStream))
   hPlayAddr   = b2l(ReadShort(fStream))
   hSongs      = b2l(ReadShort(fStream))
   hStartSong  = b2l(ReadShort(fStream))
   hSpeed      = ReadInt(fStream)
   For i = 0 To 31
      tmp = ReadByte(fStream)
      If tmp > 0 Then hName$ = hName$+Chr$(tmp)
   Next
   For i = 0 To 31
      tmp = ReadByte(fStream)
      If tmp > 0 Then hAuthor$ = hAuthor$+Chr$(tmp)
   Next
   For i = 0 To 31
      tmp = ReadByte(fStream)
      If tmp > 0 Then hCopyright$ = hCopyright$+Chr$(tmp)
   Next
   If hVersion = 2 Then
      hFlags = b2l(ReadShort(fStream))
      ReadInt(fStream) ; reserved
   EndIf
End Function

Function checkHeader()
   If hSignature$ <> "PSID" Then
      RuntimeError "No psid file!"
   EndIf
   If Not (hVersion = 1 Or hVersion = 2) Then
      RuntimeError "False psid version!"
   EndIf
   If hVersion = 1 Then
      If hDataOffset <> $0076 Then
         RuntimeError "False dataoffset!"
      EndIf
   Else
      If hDataOffset <> $007C Then
         RuntimeError "False dataoffset!"
      EndIf
   EndIf
   If hLoadAddr = 0 Then
      hLoadAddr = ReadShort(fStream) ; o_O
   EndIf
   If hSongs < 1 Then
      RuntimeError "No songs includet!"
   EndIf
   If hStartSong < 1 Or hStartSong > hSongs Then
      RuntimeError "False start song number!"
   EndIf
   If (hFlags And $0001) = True Then
      RuntimeError "Player not includet!"
   EndIf
End Function

Function b2l(value)
   ; big endian to low endian (by swapping last 2 bytes)
   Return (value And $FF) Shl 8 + ((value Shr 8) And $FF)
End Function


cpu.bb:
Code: [AUSKLAPPEN]
Global cpuMem, cpuRegA, cpuRegX, cpuRegY, cpuRegSP, cpuRegPC, cpuRegS

Const CPU_CARRY     = %00000001
Const CPU_ZERO      = %00000010
Const CPU_INTERRUPT = %00000100
Const CPU_DECIMAL   = %00001000
Const CPU_BREAK     = %00010000
Const CPU_OVERFLOW  = %01000000
Const CPU_NEGATIVE  = %10000000

Function cpuInit()
   cpuRegA  = $00
   cpuRegX  = $00
   cpuRegSP = $FE
   cpuRegPC = hInitAddr
   cpuRegS  = %00110000
End Function

Function cpuExecute(op)
   Local tmp1, tmp2, tmp3

   Select op
      Case $18 ; CLC
         If cpuRegS And CPU_CARRY Then
            cpuRegS = cpuRegS Xor CPU_CARRY
         EndIf
         cpuRegPC = cpuRegPC+1
         cpuCycles(2)
         
      Case $21 ; AND (ZP), X
         cpuAND($21)

      Case $25 ; AND ZP
         cpuAND($25)
         
      Case $29 ; AND Implied
         cpuAND($29)
         
      Case $2D ; AND Absolut
         cpuAND($2D)
         
      Case $31 ; AND (ZP), Y
         cpuAND($31)
         
      Case $35 ; AND ZP, X
         cpuAND($35)
         
      Case $38 ; SEC
         cpuRegS = cpuRegS Or CPU_CARRY
         cpuRegPC = cpuRegPC+1
         cpuCycles(2)
         
      Case $39 ; AND Absolut, Y
         cpuAND($39)
   
      Case $3D ; AND Absolut, X
         cpuAND($3D)
         
      Case $58 ; CLI
         If cpuRegS And CPU_INTERRUPT Then
            cpuRegS = cpuRegS Xor CPU_INTERRUPT
         EndIf
         cpuRegPC = cpuRegPC+1
         cpuCycles(2)
         
      Case $78 ; SEI
         cpuRegS = cpuRegS Or CPU_INTERRUPT
         cpuRegPC = cpuRegPC+1
         cpuCycles(2)
         
      Case $B8 ; CLV
         If cpuRegS And CPU_OVERFLOW Then
            cpuRegS = cpuRegS Or CPU_OVERFLOW
         EndIf
         cpuRegPC = cpuRegPC+1
         cpuCycles(2)
         
      Case $D8 ; CLD
         If cpuRegS And CPU_DECIMAL
            cpuRegS = cpuRegS Xor CPU_DECIMAL
         EndIf
         cpuRegPC = cpuRegPC+1
         cpuCycles(2)
         
      Case $F8 ; SED
         cpuRegS = cpuRegS Or CPU_DECIMAL
         cpuRegPC = cpuRegPC+1
         cpuCycles(2)

   End Select
End Function

Function cpuAND(op)
   Local tmp
   
   Select op
      Case $29 ; AND Implied
         tmp = PeekByte(cpuMem, cpuRegPC+1)
         cpuRegA = cpuRegA And tmp
         If cpuRegA And %10000000 Then
            cpuRegS = cpuRegS Or CPU_NEGATIVE
         EndIf
         If cpuRegA = $00 Then
            cpuRegS = cpuRegS Or CPU_ZERO
         EndIf
         cpuRegPC = cpuRegPC+2
         cpuCycles(2)

      Case $25 ; AND ZP
         tmp = PeekByte(cpuMem, cpuRegPC+1)
         tmp = PeekByte(cpuMem, tmp)
         cpuRegA = cpuRegA And tmp
         If cpuRegA And %10000000 Then
            cpuRegS = cpuRegS Or CPU_NEGATIVE
         EndIf
         If cpuRegA = $00 Then
            cpuRegS = cpuRegS Or CPU_ZERO
         EndIf
         cpuRegPC = cpuRegPC+2
         cpuCycles(2)

      Case $35 ; AND ZP, X
         tmp = PeekByte(cpuMem, cpuRegPC+1)
         tmp = PeekByte(cpuMem, tmp)+cpuRegX
         cpuRegA = cpuRegA And tmp
         If cpuRegA And %10000000 Then
            cpuRegS = cpuRegS Or CPU_NEGATIVE
         EndIf
         If cpuRegA = $00 Then
            cpuRegS = cpuRegS Or CPU_ZERO
         EndIf
         cpuRegPC = cpuRegPC+2
         cpuCycles(3)
         
      Case $2D ; AND Absolut
         tmp = PeekShort(cpuMem, cpuRegPC+1)
         tmp = PeekByte(cpuMem, tmp)
         cpuRegA = cpuRegA And tmp
         If cpuRegA And %10000000 Then
            cpuRegS = cpuRegS Or CPU_NEGATIVE
         EndIf
         If cpuRegA = $00 Then
            cpuRegS = cpuRegS Or CPU_ZERO
         EndIf
         cpuRegPC = cpuRegPC+3
         cpuCycles(4)

      Case $3D ; AND Absolut, X
         tmp = PeekShort(cpuMem, cpuRegPC+1)
         tmp = PeekByte(cpuMem, tmp)+cpuRegX
         cpuRegA = cpuRegA And tmp
         If cpuRegA And %10000000 Then
            cpuRegS = cpuRegS Or CPU_NEGATIVE
         EndIf
         If cpuRegA = $00 Then
            cpuRegS = cpuRegS Or CPU_ZERO
         EndIf
         cpuRegPC = cpuRegPC+3
         If (tmp-cpuRegX) And $F0 > tmp Then
            cpuCycles(5)
         Else
            cpuCycles(4)
         EndIf
         
      Case $39 ; AND Absolut, Y
         tmp = PeekShort(cpuMem, cpuRegPC+1)
         tmp = PeekByte(cpuMem, tmp)+cpuRegY
         cpuRegA = cpuRegA And tmp
         If cpuRegA And %10000000 Then
            cpuRegS = cpuRegS Or CPU_NEGATIVE
         EndIf
         If cpuRegA = $00 Then
            cpuRegS = cpuRegS Or CPU_ZERO
         EndIf
         cpuRegPC = cpuRegPC+3
         If (tmp-cpuRegY) And $FF00 > tmp And $FF00 Then
            cpuCycles(5)
         Else
            cpuCycles(4)
         EndIf
         
      Case $21 ; AND (ZP, X)
         tmp = PeekByte(cpuMem, cpuRegPC+1)+cpuRegX
         tmp = PeekShort(cpuMem, tmp)
         tmp = PeekByte(cpuMem, tmp)
         cpuRegA = cpuRegA And tmp
         If cpuRegA And %10000000 Then
            cpuRegS = cpuRegS Or CPU_NEGATIVE
         EndIf
         If cpuRegA = $00 Then
            cpuRegS = cpuRegS Or CPU_ZERO
         EndIf
         cpuRegPC = cpuRegPC+2
         cpuCycles(6)
         
      Case $31 ; AND (ZP), Y
         tmp = PeekByte(cpuMem, cpuRegPC+1)
         tmp = PeekShort(cpuMem, tmp)+cpuRegY
         tmp = PeekByte(cpuMem, tmp)
         cpuRegA = cpuRegA And tmp
         If cpuRegA And %10000000 Then
            cpuRegS = cpuRegS Or CPU_NEGATIVE
         EndIf
         If cpuRegA = $00 Then
            cpuRegS = cpuRegS Or CPU_ZERO
         EndIf
         cpuRegPC = cpuRegPC+2
         If (tmp-cpuRegY) And $FF00 > tmp And $FF00 Then
            cpuCycles(6)
         Else
            cpuCycles(5)
         EndIf
            
   End Select   
End Function

Function cpuCycles(count)
End Function


sid.bb
Code: [AUSKLAPPEN]
; stay tuned...


Mit der hLoadAddr bin ich mir noch nicht so sicher.
mfg olli
vertex.dreamfall.at | GitHub

BladeRunner

Moderator

BeitragSo, Sep 19, 2004 2:25
Antworten mit Zitat
Benutzer-Profile anzeigen
Der SID:

- Frequenzbereich von 0- ca. 4 kHz.
- 3 Tongeneratoren à 7 Register, welche (mit Ausnahme der Register von Generator 3) write-only sind.
- zusätzlicher filter (auch für externe Tonquellen)

Frequenzberechnung beim SID:

Die Frequenz eines Tones wird in den Registern 0/1 eines Generators gespeichert, allerdings in Bezug auf die Taktfrequenz des C64.
Amerikanisches Modell: 1022.7271 kHz
Europäisches Modell: 985.2484 kHz

Wert = Frequenz * 2^24/ Taktfrequenz ,wobei beide Frequenzen in Herz angegeben werden.
Das Ergebnis wird in Hi- und Lo-Byte aufgespalten:
HI = INT(WERT/256)
LO = WERT-256*HI

Eine Änderung des Wertes um 1 entspricht also einer Tonhöhenänderung von ca. 0.06 Hz.
Errechnen von Tonhöhen:
FREQUENZ = 2^(NR/12)*16.35 ,wobei NR der Anzahl der Halbtonschritte über dem Tiefsten erzeugbaren Ton (C-0) entspricht.
Anhand dieser Formel lässt sich auch eine Tabelle mit allen zur Verfügung stehenden Tonhöhen errechnen.

Die Wellenform:

- Vier Grundformen: Rechteck (mit Pulsweite), Dreieck, Sägezahn und (weisses Rauschen).
- Die Wellenform wird durch Setzen eines entsprechenden Flags in Register 4 bestimmt:
Bit4: Dreieck, Bit5: Sägezahn, Bit6: Rechteck, Bit7: Rauschen.

Es IST möglich mehrere Schwingungsformen gleichzeitig auszuwählen. Das Ergebnis des Generators ist allerdings NICHT die Summe aller Einzelformen, sondern eine logische UND-Verknüpfung der einzelnen Komponenten.
Zudem kann der Rauschgenerator bei wählen mehrerer Wellenformen blockieren - diese Blockade wird durch setzen von Bit 3 des 4en Registers aufgehoben.

Bei Rechteck: Register 2 und das LowNibble von Register 3 ergeben die Pulsweite (0-4095). 2047 entspricht einer ausgeglichenen Rechtecksform

Das Ein-/Ausschalten des Generators erfolgt durch Setzen/Löschen von Bit 0 des Registers 4.

Die Hüllkurve (ADSR):
Die Hüllkurve ist nichts anderes als ein "Lautstärkeverlauf" des zu erzeugenden Tones.

ATTACK: Bei Einschalten des Tongenerators wird die Attack-phase eingeleitet. Hier steigt die Lautstärke von 0 auf die eingestellte Maximallautstärke (LO-Nibble von Regiter 24).
Die Zeit zum Erreichen dieser Lautstärke wird über das HI-Nibble von Register 5 eingestellt.
Alle Lautstärkeverläufe sind linear.

DECAY: nach der Attack-Phase folgt die DecayPhase. Hier sinkt die Lautstärke auf den Sustainpegel (HI-Nibble von Reg. 6). Die dazu benötigte Zeit ist im LO-Nibble von Reg. 5 gespeichert.
SUSTAIN: Die Sustainlautstärke wird nun solange gehalten bis der Tongeneratur durch löschen von bit0 /Register 4 deaktiviert wird.

RELEASE: Danach fällt die Lautstärke innerhalb der im LO-Nibble von Reg. 6 eingestellten Zeit von Sustainpegel auf 0 ab.

Zitat:
TABELLE:
Wert d. Nibbles |Attackzeit(ms) |Release/Decayzeit(ms)
00 | 2 |8
01 | 8 |24
02 | 16 |48
03 | 24 |72
04 | 38 |114
05 | 56 |168
06 | 68 |204
07 | 80 |240
08 | 100 |300
09 | 250 |750
10 | 500 |1500
11 | 800 |2400
12 | 1000 |3000
13 | 3000 |9000
14 | 5000 |15000
15 | 8000 |24000
SONSTIGE FUNKTIONEN:
Register 4 Bit 1:
Setzen diese Bits synchronisiert die Grundfrequenzen zweier Generatoren. Der Tongenerator nach dem synchronisiert wird muss auf eine von 0 verschiedene Frequenz gesetzt werden. Alle übrigen Register dieses Generators sind dann funktionslos.
Es gilt:
Generator 1 : wird durch Generator 3 gesynch´t
Generator 2 : wird durch Generator 1 gesynch´t
Generator 3 : wird durch Generator 2 gesynch´t.


Register 4 Bit 2:
Setzen dieses Bits aktiviert die Ringmodulation 2er Generatoren. Der zu modulierende Generator muss auf Dreieckswelle gesetzt sein. Diese wird dann durch das kombinierte Signal der beiden Generatoren ersetzt (die Wellenform ergibt sich durch Summe und Differenz der Einzelfrequenzen).
Der Effekt tritt auch ein wenn der zugeschaltete Generator stummgeschaltet ist.
Also: Frequenz(Ziel) wird ersetzt durch Frequenz(Ziel)+Frequenz(Quelle) UND Frequenz(Ziel)-Frequenz(Quelle)
Auch hier sind die Generatoren welche sich beeinflussen hardwareseitig festgelegt:
Generator 1(Ziel) (d.h. gesetztes bit2): Modulation mit Generator 3 (Quelle)
Generator 2(Ziel): Modulation mit Generator 1 (Quelle)
Generator 3(Ziel): Modulation mit Generator 2 (Quelle).


Filter:

Der SID hat verschiedene Möglichkeiten zur Filterung der erzeugten Tonsignale (oder eines eingespeisten Audiosignales). Für all diese Filtermöglichkeiten ist eine Filterfrequenz anzugeben.
Sie wird in Register 21 und 22 gespeichert, wobei von Register 21 nur die bits 0-2 genutzt werden.
Der Wert welcher der Filterfrequenz entspricht wird wie folgt errechnet:
WERT = (F-30)/5.8182 Hz (F ist die gewünschte Filterfrequenz)

Mittels der Bits 4-6 des Registers 24 lässt sich nun die Art der Filterung festlegen:
Bit 4: Lowpass alle Frequenzen > Filterfrequenz werden um 12dB je Oktave abgeschwächt.
Entspricht einem Bassboost.
Bit 5: Bandpass alle Frequenzen <> Filterfrequenz werden um 6dB je Oktave abgeschwächt.
Entspricht einer Mittenanhebung.
Bit 6: Highpass alle Frequenzen < Filterfrequenz werden um 12dB je Oktave abgeschwächt.
entspricht einer Treble-anhebung.
Die Filter können kombiniert werden.
High- und Lowpass zusammen ergeben eine Bandsperre mit der zB. das 50Hz-Brummen ausgefiltert werden kann.

Schliesslich gibt es noch die Möglichkeit der Einstellung einer Filterresonanz. Ihre Stärke wird im HI-Nibble von Register 23 eingestellt. Höhere Werte ergeben eine höhere Resonanz, d.h. eine stärkere Anhebung des Frequenzbereiches um die Filterfrequenz.
Mittels der bits 0-2 des Registers 23 wird der Filter für einzelne Stimmen (de-)aktiviert.

Mittels bit 7 des Registers 24 kann Generator 3 lautlos geschaltet werden. (Praktisch wenn man z.B. Zufallszahlen auslesen will, siehe unten).
Die Register 25-28 sind Read-Only. Sie enthalten folgende Informationen:
25: A/D-Wandler 1
26: A/D-Wandler 2
27: Oszillator (=Generator 3)
Hier lässt sich der Zustand des Rauschgenerators 3 auslesen, was effektiv einer Zufallszahl entspricht. Hierzu muss der Generator eingeschaltet sein.
28: Hüllkurvengenerator 3: Hier lässt sich die momentane relative Lautstärke des Generators 3 auslesen. Geeignet zum verändrn von Frequenzen oder Filtern in Abhängigkeit vom aktuellen Zustand.


Zitat:
Zusammenfassung:

Register:

Adresse= $D400+ Registernummer
Generator1: |Generator2: |Generator3: |Funktion:
00 |07 |14 |LO-Byte Frequenz
01 |08 |15 |HI-Byte Frequenz
02 |09 |16 |Pulsweite LO-Byte
03 |10 |17 |Bulsweite HI-Byte (Bits 0-3)
04 |11 |18 |Bits: 0:ein/aus 1:Sync 2: Ringmod. 3: Blockadestopp 4-7 Wellenform
05 |12 |19 |Bits: 4-7:ATTACK 0-3:DECAY
6 |13 |20 |Bits: 0-3:RELEASE 4-7:SUSTAIN(Volume)
gemeinsame Register:
21 |Filterfrequenz niederwertiges Byte (nur bits 0-2)
22 |Filterfrequenz Höherwertiges Byte
23 |Bits 0-3: Filter G1/G2/G3/extern Bits 4-7: Resonanzfrequenz
24 |Bits 0-3: Gesamtlautstärke 4:LP 5:BP 6:HP 7: G3 lautlos
25-28 |siehe oben


Hoffe das hilft erstmal. Werde mich bemühen daraus ein paar Codezeilen zum einstellen der wichtigsten Features zu erstellen.
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3
Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64
B3D BMax MaxGUI

Stolzer Gewinner des BAC#48, #52 & #92
 

helium

BeitragDo, Sep 30, 2004 12:41
Antworten mit Zitat
Benutzer-Profile anzeigen
Nochmal

Zitat:

Frequenz und Samples
Was wird nun als Sample bezeichnet? Im Ton die einzelnen Daten oder der Ton selber?

Sample ist ein Begriff für beides. Ein einzelner Wert im Digitalisierten Audiostrom ist ein Sample. Vor allem im Bereich DSP wirst du den Begriff in dieser Verwendung finden.
Ein Sample ist aber auch ein ganzer Ton. Den begriff wirst du vor allem im Zusammenhang mit Samplern finden.

Zitat:
Gehen wir davon aus, ich habe einen Ton der 100 Byte groß ist, und jede Datei(singular von Daten?) ist ein Byte groß. So das ich 100 Daten für diesen Ton habe. Ein Byte kann 0 - 255 annehmen. Wird das ganze dann so im Lautsprecher angesteuert, das 255 volle Stromstärke ist, und 0 garkeine?

Naja, mit der Stromstärke passiert da wenig, eher mit der Spannung. Und die pendelt dann zwischen -Umax und +Umax, 0 ist also der maximale negative Ausschlag und 255 der maximale positive Ausschlag. 64 entspricht dann quasi 0V.

Zitat:
Was besagt die Frequenz eines Tons? Bei 1000Hz wird der Ton dann 1000 mal in der Sekunde abgespielt?

Nicht der Ton, sondern eine Schwingung. Die Dauer einer Schwingung kannst du durch t=1/f berechnen (t bedeutet in der Physik Zeit und f ist die Frequenz).
Ein Ton besteht (sollte es kein reiner Sinus sein) aus einer Fundamentalfrequenz und mehreren Harmonischen Frequenzen, die einfach vielfache dieser Frequenz sind.


Zitat:

Lowpass, Highpass und Bandsperre
Bleiben wir bei den 100 Byte und 1 Byte pro Datei. Funktioniert dann ein Lowpassfilter so, das ich meinetwegen einen bestimmten Wert (von 0 - 255) sagen wir 50 angebe, und alle Daten die unter 50 sind einfach auf 0 gesetzt werden? Das selbe für Highpass und Bandsperre wo die Daten innerhalb eines Wertebereiches auf 0 gesetzt werden.

NEIN. Das, was du da beschreibst, ist ein bekloppter verzerrer, der ziemlich fiese Frequenzen erzeugen wird.

Es gibt zwei Arten von Filtern FIR und IIR. Für erste brauchst du neben dem aktuellen Wert auch noch die vorangegangenen reingekommenen Werte. Bei IIRs brauchst du auch noch die vorangegangenen Ausganswerte.
FIR-Filter haben den Vorteil, dass man sie Phasenlinear konstruieren kann. Einen FIR-Filter kannst du ganz einfach designen, indem du das gewünschte Spektrum malst und eine umgekehrte FFT darauf anwendest.
Der Nachteil ist, das solche Filter recht lang sind (um vernüpftige Flankensteilheiten zu erzeugen) und deshalb recht rechenintensiv sind.

IIR-Filter verhalten sich generell so wie entsprechende analoge Filter. Allerdings sind sie deutlich schwieriger zu designen. Am besten du googelst nach fertigem Code. Als stichwort für die Suche: Biquad.

Zitat:

Ringmodulation

Zitat:
Das Ringmodulation bildet Summe und Differenz der an den Eingängen anliegenden Frequenzen (z.B. 3000 Hz an Eingang A und 400 Hz an Eingang B ergeben am Ausgang 2600 Hz und 3400 Hz).

Warum Frequnzen, und warum kann der Ausgang 2 Frequnzen beinhalten?

Jedes Signal (bis auf einen reinen Sinus) enthält viele Frequenzen.
Ringmodulation ist einfach eine Modulation der Amplitude eines Signals mit der Amplitude eines anderen Signals.

Code: [AUSKLAPPEN]

ergebnis = signal1 * signal2

Neue Antwort erstellen


Übersicht Ressourcen Sound & Music

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group