Hi!
Mir hat der Thread Xmega Soundcheck von Kai ziemlich viel geholfen bei
einem kleinen Sound Projekt an dem ich derzeit arbeite ( Xmega1A
Xplained Board ) .
Jetzt bin ich allerdings an einer Stelle angelangt an der mein Gehirn
einfach nur aussetzt. Wenn ich jetzt 2 Sound-Dateien als C-arrays habe
und diese mixen will, wie gehe ich da am besten vor?
ich weiss nicht ob das hier richtig ist:
(soundbyte-A / 2) + (soundbyte-B /2)
Wichtig ist auch noch. Der erste Sound der läuft ist im Grunde ein
Dauerloop eines Motoren-Geräuschs darüber möchte ich aber nun z.b noch
ein Horn oder ne Glocke spielen lassen , welche im Grunde jederzeit
starten können sollen.
Ich bin mir nicht sicher wie man hierbei vorgehen muss, daher wäre ich
für Rat sehr dankbar !
gruß Dominik
Da gibt es verschiedene Varianten. Z.B. beide 8-Bit-Samples addieren
(Übertrag landet im Carry) und dann einmal nach rechts rotieren (durch 2
teilen, incl. Carry).
Wenn ich mehr Stimmen brauche, summiere ich die Sounds mit Übertrag in
zwei Register (16-Bit-Variable) und teile sie anschließend durch die
Anzahl der Stimmen (Kanäle). Dabei achte ich darauf, dass die Anzahl
eine Zweierpotenz ist. (M)ein Dampflokgeräusch mit Tiny85 hat z.B. 4
Stimmen. Davon ist eine für die Glocke reserviert, drei für die
Dampfstöße. Alle Sounds enden im Loop für das Grundrauschen (Sieden).
Die Dampfstöße werden von einem Radsensor ausgelöst, dabei wird die Spur
hochgezählt und die Adressdaten (Anfang, Ende) in ein Array gelegt. Die
Ausgaberoutine gibt den Sound aus, bis die Endadresse erreicht ist und
fälscht den Zeiger dann auf den Siedeloop, der bei Erreichen der
Siede-Endadresse wieder auf Siede-Anfang gesetzt wird. Durch den Einsatz
von 3 Spuren für Dampfausstöße können zwei vorherige Dampfausstöße
gemütlich zu Ende laufen, während der dritte gestartet wird. Das klingt
irgendwie besser als wenn der vorherige Dampfstoß abgewürgt wird. Der
Platz im Tiny85 reicht allerdings nicht mehr für eine Dampf-Pfeife, die
kommt dann auf ein Soundrecorder-Modul und wird in den NF-Pfad zum LM386
eingekoppelt.
Bei der Diesel-Version passen Anlasser, Diesel, Glocke und Horn in einen
Tiny85. Bei der Dampf-Version Glocke, Sieden und zwei verschiedene
Dampfstöße. Letztere deshalb, um jedes vierte (oder sechste bei
Verbund-Lok) mal einen anderen Sample zu benutzen, damit es nicht wie
ein Maschinengewehr klingt.
Das Tiny85-Soundmodul sieht dann so aus:
http://www.hanneslux.de/planet5b/Harzkamel/DSCN0003.JPG
...
>> Alle Sounds enden im Loop für das Grundrauschen (Sieden).
Das heißt im Grunde genommen werden die anderen Sounds nur in das
Grund-Rauschen "eingekoppelt" mathematisch? also in den jeweiligen
Buffer?
Dominik Walter schrieb:>>> Alle Sounds enden im Loop für das Grundrauschen (Sieden).>> Das heißt im Grunde genommen werden die anderen Sounds nur in das> Grund-Rauschen "eingekoppelt"
Naja, eher "ersetzt"... Das gilt aber nur für die Dampf-Variante. Beim
Diesel hat jedes Geräusch seine eigene "Spur", der Motor (und Anlasser)
auch noch seinen eigenen Timer-Interrupt wegen der Drehzahländerung
(Änderung der Ausgaberate).
> mathematisch? also in den jeweiligen> Buffer?
Es laufen (beim Dampf) 4 Spuren. Jede Spur gibt das Grundrauschen (sehr
geringe Lautstärke, also Werte um die 128) aus, solange sie nichts "zu
tun" hat. Die Zeiger auf die Streams (laufende Adresse und Endadresse)
liegen in einem Array. Dies ermöglicht Gleichbehandlung aller Spuren
(durch Unterprogramm, das nur den Index übergeben bekommt) bei der
Ausgabe, reduziert also den Programmcode. Erreicht die (im Array
gehaltene) laufende Adresse einer Spur die (auch im Array liegende)
Endadresse, so wird die laufende Adresse auf Anfang des Grundrauschens
"gefälscht".
Um einen Sound zu starten, wird nur Anfangs- und Endadresse (Flash) des
entsprechenden Sounds in das Array geschrieben. Den Rest macht die
Ausgaberoutine dann selbst.
Der Start wird über Steuerleitungen ausgelöst, die softwaremäßig
entprellt werden. Für die Glocke läuft ein eigener Zähler, der über die
Steuerleitung auf Startwert gesetzt wird. Bei Auslösung durch
Fernsteuerung (DCC, Funk) wird dieser auf 1 gesetzt. Soll die Glocke
über einen am Gleis "vergrabenen" Magneten ausgelöst werden, wird der
Zähler auf die Anzahl der gewünschten Glockenschläge gesetzt.
Ich habe vor, das Ganze irgendwann noch mal mit einem Mega1284
umzusetzen, um mit höherer Samplerate und mehr (und längeren) Sounds
arbeiten zu können. Mich stört dabei aber etwas, dass es keine PLL für
Timer gibt, die PWM-Frequenz des als DAC genutzten Timers also begrenzt
ist. Ein externer DAC macht die Sache ja wieder komplizierter. Mit dem
Tiny85 erreicht man ja ohne Klimmzüge 250 kHz PWM-Frequenz, was die
Ansprüche an den Tiefpass erheblich reduziert. Ideal dafür wäre ein
Tiny25 mit 1 oder 16 MB internem EEP (der auch gut als Datenlogger
geeignet wäre). Aber den haben wir leider nicht... 8-(
...
Dominik Walter schrieb:> (soundbyte-A / 2) + (soundbyte-B /2)
Wichtig ist halt, dass Du die Division nicht nur durchführst, wenn beide
Sounds ertönen, weil Du sonst den Loop immer in der Lautstärke
veränderst, wenn was anderes dazu kommt (gern gemachter Anfängerfehler
:). Wenn es immer nur um die zwei Sounds geht, kannst Du die Werte auch
von vornherein auf 7 Bit reduzieren, dann sparst Du Dir die Division.
Mirko
Ich habe es jetzt so weit das ich insgesamt 8 Kanäle gleichzeitig
abspielen kann. Insgesamt auf einige Timer verteilt (Motor /
Anlasser/gas-geben ist Pitch-bar).
Ich bin jetzt allerdings an der stelle angelangt wo der interne Flash
Speicher nicht mehr ausreicht.
Im Augenblick arbeite ich mit 11khz bei 8bit , ich würde aber gerne
wieder auf 22khz oder 44khz hoch , weil der 11khz sound doch sehr ..
naja dürftig ist ;)
Ich würde daher gerne auf SD karte als Sound speicher gehen. Ich weis
wie ich die SD-Lese-Routinen einbinden muss. allerdings ist mir das
Konzept nicht ganz schlüssig wie ich es schaffe mehrere Sounds
gleichzeitig von der SD karte abzuspielen. (sofern das überhaupt geht!)
Der XmegaA1 auf dem ich arbeite hat zwar einen Externen RAM mit so weit
ich weis 64Mbit (Xplained Board) , aber wie ich das genau in der
Software anspreche weis ich noch nicht. Auch hatte ich in einem anderen
Forum gelesen das es mit solch großen Ram-Bausteinen und AVR-GCC ein
Problem gibt mit den 16bit Pointer und damit verbundenen maximal
Adressierbaren speicher von 64k?
der Logik halber nach müsste ich (korrigiert mich wenn ich falsch liege)
zu Anfang bei Programmstart von der SD karte die Sounds in den Externen
RAM laden und dann den externen RAM in meine Abspiel-Routinen füttern ,
anstelle wie im Augenblick einfach auf Arrays im Programmspeicher zu
verweisen.
Falls irgend jemand das schon gemacht hat und mir helfen kann ich bin
für jeden Rat dankbar, da ich nun nach mehrmaligem suchen keine einfach
verständliche Anleitung gefunden habe.
PS: Eine Sache die ich nicht ganz verstehe... wieso kann ich
eigentlich bei meinem Xmega128 nur die ersten 64Kb für Progmem Daten
verwenden?..
Dominik Walter schrieb:> wieso kann ich> eigentlich bei meinem Xmega128 nur die ersten 64Kb für Progmem Daten> verwenden?..
Ich habe zwar noch keinen Xmega eingesetzt, aber eigentlich sollte er
das können. Das Register RAMPZ ist vorhanden und der Befehl ELPM wird
auch unterstützt.
...