Grundlegendes
Übersicht

![]() |
VertexBetreff: Grundlegendes |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Achtung Halbwissen aus grauer Vorzeit
![]() Sample ist die komplette Sammlung aller Daten. Ein einzelnes Datum (Einzahl von Daten ![]() 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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Der SID, ja ... das waren noch Sounds.... (daher hab ich übrigens mein angestaubtes Wissen ![]() 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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Da gibt es schon massig Lösungen. ( HardSID , VSt Plugin etc ) | ||
Forbiddenmagic - Warfare of Forgotten Power |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich habe mal jetzt alles zusammengefasst, was ich durch dich und andere Quellen so erfasst habe:
The SID Project
http://cbmmuseum.kuto.de/zusatz_6581_sid.html (es sind 29 Register, die Frequenz geht von 0 bis ca. 4 kHz und die Releasephase ist exponentiell) http://www.buchi.de/ParallelSID/6581.PDF (englisches Datenblatt, schlechte Qualität) http://www.joogn.de/b/6581.de.zip (deutsches Datenblatt, sehr gute Quailtät) http://aachen.heimat.de/leute/...ta/c64.pdf (Die SID Adresse ist nicht 54272 sondern 53272 und die Decayphase ist nicht exponentiell sondern linear) http://www.viceteam.org/ (der X128 Emulator kann als Einzigster den SID emulieren) http://nmc.uoregon.edu/emi/emp_win/main.html (sehr gutes englisches Synthesizerlexikon)
- 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 |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() Antworten mit Zitat ![]() |
---|---|---|
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 |
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
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:
SONSTIGE FUNKTIONEN:
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 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 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
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 |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group