Hallo,
ich möchte auf einem PSoC 5LP Klänge wiedergeben. Leider hat der
Controller nur einen 8-Bit DAC :( Ich bin mir also bewusst, dass es
nicht so arg berauschend sein wird.
Um zu sehen, ob das überhaupt einigermaßen akzeptabel klingt, habe ich
das Beispielprogramm für eine USB-Soundkarte ausprobiert. Die
Audiosignale werden über die internen OpAmps geleitet, 470R + 100uF in
Reihe, um DC zu entkoppeln und dann an ganz normale passive
16R-Kopfhörer.
Ein paar Lieder abgespielt, und sooo schlecht fand ich's gar nicht. Also
hab ich für erste Tests eine Sinustabelle mit 512 Einträgen angelegt,
und gebe diese mit 512kHz aus, also 1kHz Sinus. Hört sich auch noch
soweit gut an.
Im zweiten Schritt habe ich versucht, das Signal mit einer
Dreieckspannung mit etwa 0.5Hz zu multiplizieren, um die Lautstärke
einstellen zu können. Und hier habe ich nun das Problem, dass ich bei
Verwendung der Kopfhörer eine Art Sirren mit drin habe. Das habe ich
ohne Lautstärkeänderung nicht.
Ich wollte das ganze dann am PC aufnehmen, damit ich "zeigen" kann, was
ich meine. Aber da taucht das Sirren nicht auf, also ist auf dem Weg in
den Rechner wohl was drin, was bei den Kopfhörern fehlt.
Interessanterweise taucht das Sirren auch bei Verwendung der Schaltung
als USB-Soundkarte nicht auf - per NAudio/C# habe ich das 1kHz
Sinussignal mit einer Dreieckspannung von 0.5Hz multipliziert und
ausgegeben, kein Sirren. Wie bereits erwähnt, auch das Abspielen von
Liedern klang relativ gut, ebenfalls kein Sirren.
Hat jemand eine Idee, woran das liegen könnte? Zwischen Beispielprogramm
und meiner Implementierung ist wie gesagt die Samplingrate
unterschiedlich (32kHz im Beispiel vs. 512kHz zu meiner
Implementierung).
Ralf
Vergessen zu erwähnen:
die Amplitude beträgt ca. 1V direkt am Controller, d.h. über den 470R
Widerstand wird der Strom weit genug begrenzt, damit die OpAmps nicht
klippen.
Ralf
> Dreieckspannung mit etwa 0.5Hz zu multiplizieren,> um die Lautstärke einstellen zu können
Dreieckspannung?
Also ich multipliziere mit einem (festen) Wert kleiner 1, um die
Lautstärke abzuschwächen.
Und ja, 8 bit klingen nicht schlecht, nur ist das
Quantisierungsrauschen recht hoch, und das wird mit abgeschwächter
Lautstärke nur noch störender.
Hi,
>> Dreieckspannung mit etwa 0.5Hz zu multiplizieren,>> um die Lautstärke einstellen zu können> Dreieckspannung?> Also ich multipliziere mit einem (festen) Wert kleiner 1, um die> Lautstärke abzuschwächen.
Ja, das ist wie gesagt als erster Test, damit ich sehe, wie sich
Änderungen der Lautstärke auswirken.
Ralf
Mir ist zwar nicht klar, was man bei 0.5 Hz testen kann, aber okay.
> eine Art Sirren mit drin habe
Da hätte ich gesagt (und selbst oft genug erlebt), das kann aus mehreren
Quellen stammen, aber da gilt
> Das habe ich ohne Lautstärkeänderung nicht.
bin ich jetzt etwas ratlos.
Hat der PSOC nicht auch programmirbare Logik? Da sollte sich ziemlich
einfach ein Sigma-Delta Wandler realisieren lassen.
Ansonsten gäbe es noch die Möglichkeit, die SPI für Sigma-Delta zu
missbrauchen. Das dürfte einen deutlich besseren Klang als der 8Bit-DAC
geben.
@ S. Landolt:
> Mir ist zwar nicht klar, was man bei 0.5 Hz testen kann, aber okay.
Was ist nicht klar? Jede Sekunde bin ich auf 0% oder 100% der
Signalamplitude.
@Cornelius:
> Hat der PSOC nicht auch programmirbare Logik? Da sollte sich ziemlich> einfach ein Sigma-Delta Wandler realisieren lassen.> Ansonsten gäbe es noch die Möglichkeit, die SPI für Sigma-Delta zu> missbrauchen. Das dürfte einen deutlich besseren Klang als der 8Bit-DAC> geben.
Ja, er hat programmierbare Logik. Mit der will ich es auch
implementieren, bzw. hab ich bereits. Da diese aber das Sirren hat, hab
ich es erstmal weitgehend in Software gemacht, um Fehler in der
Implementierung auszuschließen - nur um festzustellen, dass es da
genauso ist :)
Also wird es die Implementierung sein, aber ich kann's mir halt nicht
erklären - A*B ist nun ja nicht wirklich schwer...
Ralf
>Ja, er hat programmierbare Logik. Mit der will ich es auch>implementieren, bzw. hab ich bereits.
Da ist mir nicht ganz klar, was Du jetzt implementiert hast: Den Sigma
Delta DAC?
>> Ja, er hat programmierbare Logik. Mit der will ich es auch>> implementieren, bzw. hab ich bereits.> Da ist mir nicht ganz klar, was Du jetzt implementiert hast: Den Sigma> Delta DAC?
Ich verwende den internen 8-Bit DAC im Stromquellenbetrieb. Die
programmierbare Logik habe ich verwendet, um die Multiplikation
durchzuführen. Die Sinustabelle kommt per DMA rein und die eingestellte
Lautstärke wird per Control Register eingegeben.
Aber wie gesagt: die Hardware-Implementierung hab ich wieder komplett
rausgenommen, da ich das Sirren drin habe. D.h. jetzt läuft es so, wie
es auf den meisten Controllern läuft, in Software:
1) Interrupt 512kHz: holt Wert aus Sinustabelle, multipliziert mit
aktueller Lautstärke, raus auf den DAC
2) Interrupt 250Hz: inkrementiert/dekrementiert die Lautstärke
zu 2) Die Lautstärke ist ebenfalls ein 8-Bit Wert, dieser wird im
Interrupt inkrementiert, wenn er kleiner 255 ist, ansonsten wird die
Richtung umgekehrt, also dekrementiert, wenn 0 erreicht ist, wird wieder
inkrementiert, etc., das ergibt somit eine Dreieckspannung mit ca.
0,5Hz.
Ralf
Ralf schrieb:> Interrupt 512kHz: holt Wert aus Sinustabelle, multipliziert mit> aktueller Lautstärke, raus auf den DAC> 2) Interrupt 250Hz: inkrementiert/dekrementiert die Lautstärke>> zu 2) Die Lautstärke ist ebenfalls ein 8-Bit Wert, dieser wird im> Interrupt inkrementiert, wenn er kleiner 255
Wenn Lautstärke bis 255 geht, was ist dann der Wertebereich für die
Sinustabelle mit der Du multiplizierst? 0 bis 1? Was machst Du wenn Dein
Produkt nicht in 8 bit darstellbar ist?
Hi Dumdi,
> Wenn Lautstärke bis 255 geht, was ist dann der Wertebereich für die> Sinustabelle mit der Du multiplizierst? 0 bis 1? Was machst Du wenn Dein> Produkt nicht in 8 bit darstellbar ist?
Die Sinustabelle geht natürlich auch bis 255 :)
Ich verwende das Highbyte vom Ergebnis. Die Sinustabelle selbst ist
vorzeichenbehaftet abgelegt, die Lautstärke ist vorzeichenlos. Die
Multiplikation erfolgt ohne Vorzeichen, berücksichtigt das aber
entsprechend - zumindest sieht es auf dem Oszi nicht verkehrt aus:
1
if(Value<0x80){
2
Value=(Value*Ampl)>>8;
3
}
4
else{
5
Value=((Value*Ampl)>>8)-Ampl;
6
}
7
Value^=0x80;
Der "Ruhepegel" ist also bei 128 (0x80). Die Sinuswerte gehen von 1 bis
255 (127 symmetrisch um 128).
Ralf
Ralf schrieb:> Die Sinustabelle geht natürlich auch bis 255 :)> Ich verwende das Highbyte vom Ergebnis. Die Sinustabelle selbst ist> vorzeichenbehaftet abgelegt, die Lautstärke ist vorzeichenlos. Die> Multiplikation erfolgt ohne Vorzeichen,
Ist das ein Ratespiel?
Welche Datentype verwendest Du? Int_8 fuer den Sinus? Int_16? Uint?
Mach ein 'vollstaendiges' Beispiel.
Lass Dir mal die berechneten Daten in einer Tabelle ausgeben.
Was du hörst könnte auch Quantisierungsrauschen sein.
Dein 8-Bit-DAC hat ja 255 diskrete Stufen. Und das Umschalten zwischen
denen hört man. Im Prinzip hast du bei 8 Bit einen sehr geringen
Dynamikumfang. Die Reduktion der Lautstärke auf 50% verringert deine
Auflösung um 1 Bit.
bei 25% Lautstärke hast du nur noch 6Bit Auflösung. Und das ist
mieserabel.
Helfen tut dagegen eben nur eine höhere Auflösung, oder eine analoge Art
der Lautstärkeneinstellung.
Tipp:
Ich habe mir mal einen MP3-Player mit µC gebaut, und dort halt einen
UDA1334 verwendet und mittels I2S gefüttert. PIC32 bieten das nativ.
Mit der Tonqualität bin ich zufrieden.
Bei der heutigen ekelhaften Rumsbums-Musik brauchst eh nicht mehr als
8-Bit. Volle 16 Bit hat man früher für Klassik-Musik benötigt.
Zudem kannst du mit den heutigen schnellen CPUs noch oversamling machen,
das bringt dann nochmal ein paar Bit.
Und ich glaube auch dass das Sirren vom Oversampling her kommt. Dreh mal
runter obs weg geht.
CPU Historiker schrieb:> Bei der heutigen ekelhaften Rumsbums-Musik brauchst eh nicht mehr> als 8-Bit. Volle 16 Bit hat man früher für Klassik-Musik benötigt.>
Hallo,
also hierfür benötigt man 16 Bits oder früher haben die Vorfahren diese
Musik von einer schlecht gepressten Schallplatte gehört, die extra für
Schall gemacht war:
https://m.youtube.com/watch?v=uPRetJ-xyio
MfG
@Dumdi D:
> Ist das ein Ratespiel?
Nein.
> Welche Datentype verwendest Du? Int_8 fuer den Sinus? Int_16? Uint?
Ja, ist int8.
> Mach ein 'vollstaendiges' Beispiel.
Was ist ein vollständiges Beispiel für dich? Oben gezeigt ist der Teil
der Interruptroutine. Wobei ich da vergessen habe zu erwähnen, dass
'Value' und 'Ampl' beide uint8 sind, d.h. in Value landet der int8 Wert
der Sinustabelle. Von daher Asche auf mein Haupt. Vollständiger wird das
als Beispiel aber m.E. nicht.
> Lass Dir mal die berechneten Daten in einer Tabelle ausgeben.
Ist das jetzt auch ein Ratespiel? :) Welche, der reine Sinus oder nach
der Multiplikation?
@soso:
> Was du hörst könnte auch Quantisierungsrauschen sein.> ...> bei 25% Lautstärke hast du nur noch 6Bit Auflösung. Und das ist> mieserabel.>> Helfen tut dagegen eben nur eine höhere Auflösung, oder eine analoge Art> der Lautstärkeneinstellung.
Warum habe ich das Sirren dann nicht, wenn ich das
USB-Soundkartenbeispiel verwende? Da habe ich "nur" das
Hintergrundrauschen, welches man noch von den Walkmans vom Anfang der
90er kennt :)
@CPU Historiker:
> Und ich glaube auch dass das Sirren vom Oversampling her kommt. Dreh mal> runter obs weg geht.
Verstehe ich nicht :o welches Oversampling? Du meinst, die 512kHz sind
zu schnell?
Ralf
Ralf schrieb:> Der "Ruhepegel" ist also bei 128 (0x80). Die Sinuswerte gehen von 1 bis> 255 (127 symmetrisch um 128).
Dann ist Deine Berchnungsfunktion leider kompletter Murks.
Betrachten wir den Fall Value < 128, AMP klein,sagen wir mal 1 (eins):
1
if(Value<0x80){
2
Value=(Value*Ampl)>>8;
Das Ergebnis liegt nahe Null unabhängig von Value. Was ungünstig ist,
denn es müsste ja eigentlich nahe des Ruhepegels von 128 liegen.
Implementiere das mal auf dem PC und gebe es an der Konsole als CSV aus
(jeweils Value und Value * AMP).
Das kann man in Excel (LibreOffice) einlesen und plotten.
@Jim:
> Das Ergebnis liegt nahe Null unabhängig von Value. Was ungünstig ist,> denn es müsste ja eigentlich nahe des Ruhepegels von 128 liegen.
Deswegen:
1
Value^=0x80;
Damit stelle ich quasi den Ruhepegel wieder her.
Ralf
Könnte es sein, dass Dein Mikrocontroller einfach Probleme hat den
niedrigohmigen Kopfhörer zu treiben? Wenn das Signal an der Soundkarte
(LineIn 10kOhm / MicIn 3kOhm) sauber ist und mit dem Kopfhörer (ca.
80-200 Ohm) merkwürdige Geräusche auftreten, dann ist da vielleicht
intern irgendeine Schaltung ausgelastet den Strom zu regeln und streut
ein.
Schließe doch mal den Kopfhörer an und greife davor mit dem Oszilloskop
ab. Vielleicht bekommst Du dann was zu Gesicht.
Evtl. könntest Du auch mal vor dem Kopfhörer das Signal abgreifen und
parallel an die Soundkarte weitergeben. Wenn du dann auch Nebengeräusche
hörst, könnte könnte man das Problem weiter eindämmen. Und Du könntest
es für uns hörbar machen.
Hallo Toli,
> Könnte es sein, dass Dein Mikrocontroller einfach Probleme hat den> niedrigohmigen Kopfhörer zu treiben? Wenn das Signal an der Soundkarte> (LineIn 10kOhm / MicIn 3kOhm) sauber ist und mit dem Kopfhörer (ca.> 80-200 Ohm) merkwürdige Geräusche auftreten, dann ist da vielleicht> intern irgendeine Schaltung ausgelastet den Strom zu regeln und streut> ein.
Der Kopfhörer hat 16R, und momentan sind 470R vorgeschaltet. Der interne
OpAmp kann 25mA. Der Spitze-Spitze-Wert direkt am OpAmp-Ausgang liegt
bei etwa 0,6V-1,0V. Also sind's etwa 2mA, die fließen.
> Schließe doch mal den Kopfhörer an und greife davor mit dem Oszilloskop> ab. Vielleicht bekommst Du dann was zu Gesicht.
Gute Idee, ich hatte nur mal direkt am OpAmp-Ausgang gemessen.
> Evtl. könntest Du auch mal vor dem Kopfhörer das Signal abgreifen und> parallel an die Soundkarte weitergeben. Wenn du dann auch Nebengeräusche> hörst, könnte könnte man das Problem weiter eindämmen. Und Du könntest> es für uns hörbar machen.
Du meinst, der Kopfhörer erzeugt die Störgeräusche selbst? Ich schau
mal, ob ich das so hingebastelt bekomme, um beides abgreifen zu können.
Aber wie gesagt, Kopfhörer + USB-Audio hat keine Störungen.
Ralf
Ralf schrieb:> Du meinst, der Kopfhörer erzeugt die Störgeräusche selbst?
War nur eine Vermutung und Einlassung, da Du Dich ja gewundert hattest,
was der Unterschied zwischen Soundkarteneingang und Kopfhörer ist. Wenn
sich die Störgeräusche reproduzierbar verhindern lassen, wenn du an den
Soundkarteneingang anschließt, wäre es zumindest lohnenswert da mal
einzugrenzen.
Evtl. ist Dein Problem aber auch völlig woanders zu suchen. Wie gesagt,
wäre gut, wenn man das ganze mal hören könnte.
Hallo Toli,
>> Du meinst, der Kopfhörer erzeugt die Störgeräusche selbst?> War nur eine Vermutung und Einlassung, da Du Dich ja gewundert hattest,> was der Unterschied zwischen Soundkarteneingang und Kopfhörer ist. Wenn> sich die Störgeräusche reproduzierbar verhindern lassen, wenn du an den> Soundkarteneingang anschließt, wäre es zumindest lohnenswert da mal> einzugrenzen.
Werd ich machen, aber ich muss erst Material besorgen, das gibt die
Bastelkiste nicht mehr her :D
> Evtl. ist Dein Problem aber auch völlig woanders zu suchen. Wie gesagt,> wäre gut, wenn man das ganze mal hören könnte.
Ich hab die Testsoftware mal modifiziert. Anstatt per Dreieckspannung
die Amplitude zu modifizieren, kann ich nun per UART schrittweise den
Multiplikator hoch/runter zählen und damit für jeden Wert die Ausgabe
anhören.
Hätte ich vorher schon tun sollen, denn dabei sind zwei Sachen
aufgefallen:
1) beim Ändern der Werte tritt mitunter eine Störung auf. Hier muss ich
schauen, ob das bei jeder Änderung vorkommt. Ich ändere die Amplitude
nur beim Nulldurchgang, das scheint jedoch nicht zu helfen.
2) nicht alle Kombination hören sich sauber an. Bei ganz kleinen
Amplituden ist es natürlich klar, da besteht das Signal ja nur aus ein
oder zwei Stufen. Ich hab auch mal eine FFT über verschiedene Amplituden
laufen lassen, da sehe ich mitunter Oberwellen der 1kHz Frequenz. Ich
werd da mal eine ordentliche Messreihe machen.
Ich will auch mal schauen, dass ich das USB-Audio Beispiel so herrichten
kann, dass die Werte vom eingangs erwähnten Testprogramm, die im PSoC
ankommen, erfassen kann. Dann sehe ich, ob das noch in irgendeiner Weise
durch eine Audio-API modifiziert wird.
Sehr interessantes und lehrreiches Thema, wie ich finde :)
Ralf