Forum: Mikrocontroller und Digitale Elektronik Acht 8bit Samples mischen


von Jonas Biensack (Gast)


Lesenswert?

Tag zusammen,

hab mal eine Frage-

Vorgeschichte:

Ich habe ein mini Sampler für einen Atmega32 geschrieben. Dazu habe ich 
mit audio-converter 8 Samples in (8 bit Mono 8000Hz) konvertiert und 
diese auf den atmega in den flash geschrieben. Ein kleine Routine 
verarbeitet dann einen ganz einfach gehalten Sequenzer der die Samples 
abspielt. Ein 12 bit
Widerstandsnetzwerk sorgt für die DA-Umwandlung. Ich habe also an einer 
Stelle acht byte-werte (jedes für ein Sample) die ich mischen möchte. 
Bis dato gehe ich einfach hin und addiere alle acht werte und gebe sie 
auf dem DA-Wandler aus.

OUT = S1 + S2 + S3 + S4 + S5 + S6 + S7 + S8

8 * 255 = 2040 als maximalen Wert der ausgegeben werden muss

Das sollte also mit dem 12bit wandler kein problem sein. Las ich nun 
einzelne Samples abspielen geht alles gut, klingt "sauber" solange man 
das bei 8 bit sagen kann. Wobei die Basedrums und Toms gar nicht so 
schlecht klingen.

Meine Frage:

Gibt es eine bessere / richtige Möglichkeit die Samplewerte zu mischen?

Die Lautstärke könnte ich so regeln, oder?
Wobei Vn ein Wert zwischen 0 und 1 sein sollte.

OUT = (S1*V1) + (S2*V2) + (S2*V2) + ...

Ideen, Kritik alles erwünscht. Danke schonmal.

von dasrotemopped (Gast)


Lesenswert?

Hallo Jonas,

um mehrere Samples zu mischen erst mal etwas Mathe.
Wenn du mehrere Samples mit 8 Bit Auflösung mischst
ist auch das Ergebnis nur in 8 Bit aufgelöst.
In deiner Rechnung fehlt der Teiler durch die Anzahl
der gemischten Samples :

Out = ( In1 + In2 + ... + InX ) /X

Da du eine 32 Bit CPU benutzt solltest du im Programm Code
darauf achten, das du keine Rechenfehler (durch falsche Rundung )
bekommst durch 8 Bit Variablen ( das Ergebnis der Addition von 2
8 Bit Variablen muss in einer 16 Bit Variablen gespeichert werden.
Das Selbe gilt bei der Division : Das teilen einer 16 Bit
Variablen durch eine 8 Bit Variablen hat muss als Ziel eine 16 Bit
Variable haben. Der Compiler rundet und wandelt zwischen den 
Variablengrössen gerne mal anders als man erwartet.

Zum Test der Software ist es praktisch, 2 Samples mit einem Sinus
mit der Frequenz 1 kHz und 2 kHz abzuspielen und die Ausgabe sich
auf dem Oszilloskop anzuschauen. Zusammengemischt sollten die Peak
Werte nicht höher sein als ein Peak wert eines einzelnen Samples.

Wenn dein DA Wandler nur positive Spannungen erzeugt, kann die 
Tonqualität
auf einen Audio Verstärker noch besser werden, wenn du mit einem
Kondensator den Gleichstromanteil ausfilterst.

Perfekt wird es erst wenn du in Software mit vorzeichenbehafteten Werten
rechnest und die Wandlung ebenso erfolgt.

Gruß,

dasrotemopped.

von Karl H. (kbuchegg)


Lesenswert?

dasrotemopped schrieb:


Mit dem meisten bin ich einverstanden. Aber ein paar Punkte lassen mir 
dann doch die Haare zu Berge stehen.

> Da du eine 32 Bit CPU benutzt

Prust. Nö, auch ein Mega32 ist nur eine 8 Bit CPU.
Das 32 im Namen bezieht sich auf die Größe des Flash

> solltest du im Programm Code
> darauf achten, das du keine Rechenfehler (durch falsche Rundung )
> bekommst durch 8 Bit Variablen ( das Ergebnis der Addition von 2
> 8 Bit Variablen muss in einer 16 Bit Variablen gespeichert werden.

Soweit, so gut

> Das Selbe gilt bei der Division : Das teilen einer 16 Bit
> Variablen durch eine 8 Bit Variablen hat muss als Ziel eine 16 Bit
> Variable haben.
> Der Compiler rundet> und wandelt zwischen den
> Variablengrössen gerne mal anders als man erwartet.

Auch das nicht.
Je nachdem was genau du unter "Compiler" verstehst. Ich geh mal von 
einem C Compiler und Integer Rechnung aus. Die Regeln, wie die 
Operationen ausgeführt werden, sind eindeutig festgelegt. Wenn da also 
nicht das passiert, was du erwartest, dann ist deine Erwartung falsch. 
Ein Blick in die nächstbeste C-Literatur kann das aber beheben.
Und nein: Bei Integer-Rechnungen wird überhaupt nicht gerundet. Die 
Berechnung wird so durchgeführt, als ob entstehende Kommastellen einfach 
abgeschnitten werden würden. Das ist sogar so etwas wie ein allgemeines 
Prinzip, da es auch dann zur Anwendung kommt, wenn ein Floating Point 
Ergebnis an einen Integer zugewiesen wird.

von MCUA (Gast)


Lesenswert?

Ich denke, das Wort "mischen" ist nichtssagend, denn der konkr. 
Algorithm. ist entscheidend. Und da gibt es viele....

von dasrotemopped (Gast)


Lesenswert?

Mea culpa,

Hat sich ein Tippfehler schwer ausgewirkt :

> Da du eine 32 Bit CPU benutzt
korrigiert : Da du >k<eine 32 Bit CPU benutzt

Warum sollte ich mir Gedanken um 8 oder 16 Bit machen wenn ich als 
default 32 Bit zur Verfügung habe ?

Und mit Rundung meinte ich Über/Unterlauf bei einer Rechenoperation.
Der C Kompiler mag nach Definition immer richtig arbeiten, nur hat man
nicht immer alle Definitionen auswendig im Kopf oder beachtet nicht alle 
beim Programmieren.
Daher auch mein Tip, die Rechenergebnisse per Oszilloskop zu 
"überprüfen".

@MCUA

Welchen Mischalgorithmus würdest du Jonas denn bei seiner Frage 
empfehlen ?

Gruß,

dasrotemopped

von Karl H. (kbuchegg)


Lesenswert?

dasrotemopped schrieb:
> Mea culpa,
>
> Hat sich ein Tippfehler schwer ausgewirkt :
>
>> Da du eine 32 Bit CPU benutzt
> korrigiert : Da du >k<eine 32 Bit CPU benutzt


Bamm! (das war die Stirn, die auf der Tischplatte aufschlägt)

Jetzt ergibt auch der komplette Satz auf einmal Sinn. Und ich hab mich 
schon gefragt: Was will uns der Dichter eigentlich sagen. Aber auf ein 
fehlendes 'k' bin ich nicht gekommen.

> Und mit Rundung meinte ich Über/Unterlauf bei einer Rechenoperation.
> Der C Kompiler mag nach Definition immer richtig arbeiten, nur hat man
> nicht immer alle Definitionen auswendig im Kopf oder beachtet nicht alle
> beim Programmieren.

Na ja
Die sollte man aber eigentlich schon im Kopf haben. Das man nicht immer 
darauf achtet, gestehe ich gerne zu. Nichts desto trotz sollte das so 
selbstverständlich sein, wie 'Punkt vor Strich'-Rechnen in der 
Mathematik.

von Philip (Gast)


Lesenswert?


von Mirko H. (m1rk0)


Lesenswert?

dasrotemopped schrieb:
> um mehrere Samples zu mischen erst mal etwas Mathe.
> Wenn du mehrere Samples mit 8 Bit Auflösung mischst
> ist auch das Ergebnis nur in 8 Bit aufgelöst.

Ich denke da hat MCUA schon recht, das ist eine Definitionsfrage. Das 
Ergebnis muss doch keineswegs wieder in den gleichen Wertebereich 
gezwängt werden. Da er den Hardwareaufwand offenbar nicht scheut, ist 
Jonas' Lösung doch durchaus besser.

Bei den 12-bit mit R2R stellt sich mir aber die Frage, ob das an den 
Ausgängen eines 8-bit µC so einfach geht. Irgendwo habe ich mal eine 
Lösung mit zwei 8-bit D-Flipflops gesehen, die erst mit je einem Byte 
eines 16-Bit-Samples geladen wurden um das dann gleichzeitig auf das 
Wiederstandsnetz loszulassen. Wenn man direkt die Ausgänge des AVR 
nimmt, dann hat man doch das Problem, dass der Wert zwischen zwei 
Kopieraktionen mal nicht stimmt, oder geht das irgendwie einfacher?

Mich würde das Projekt durchaus mal näher interessieren, einen 
Drumcomputer möchte ich auch irgendwann mal bauen.

Mirko

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.