Forum: Mikrocontroller und Digitale Elektronik Audiowidergabe Grundlagenverständnisproblem


von Gendo I. (gendoikari)


Lesenswert?

Hallo,

es gibt zwar viele ähnlich Projekte aber keine haben mich weiter 
gebracht.

Ich lese mit meinem STM32(wird bei jedem uC mit DAC ähnlich sein) ein 
16bit wave (RAW) file ein. Der DMA übergibt 12 MSBit in das DAC Register 
und mittels Timer trigger welcher auf 48kHz läuft wird der 12bit Wert in 
das Ausgaberegister gegeben. Alles wie im Handbuch, aber es klingt eher 
nach Weltraumgeräuschen, als nach meinem Audiofile...

Jetzt meine Fragen:

- ist es Richtig den Trigger timer, welcher die 12bit in das 
Ausgaberegister schiebt auf der Samplingrate der Audiofiles laufen zu 
lassen, also 48kHz in diesem Fall

- Kann man überhaupt den Lautsprecher, von eine Audiogrußkarte, direkt 
an den DAC und die andere Seite auf GND anschließen

- hat das 16bit wave file, welches ich mit audacity exportiert habe, 
plus und minus?
- kann ich das wavefile in ein uint16 array einlesen oder muss es in ein 
int16?

von Troll dich Troll (Gast)


Lesenswert?

Schon Freitag?

von Joachim B. (jar)


Lesenswert?

Gendo I. schrieb:
> - Kann man überhaupt den Lautsprecher, von eine Audiogrußkarte, direkt
> an den DAC und die andere Seite auf GND anschließen

man kann fast ALLES überall anschliessen, ob ein Ton rauskommt steht auf 
einem anderen Blatt.
https://etel-tuning.eu/486-thickbox_default/adapter-drehstrom-auf-gardena.jpg

Gendo I. schrieb:
> - hat das 16bit wave file, welches ich mit audacity exportiert habe,
> plus und minus?

schau mit einem HEXmonitor rein, bzw dekodiere die Werte denn deine 
Einstellungen kenne ich nicht.
https://www2.ak.tu-berlin.de/~fhein/Alias/Studio/ProTools/audio-formate/wav/overview.html

von Mark S. (voltwide)


Lesenswert?

Gendo I. schrieb:
> - Kann man überhaupt den Lautsprecher, von eine Audiogrußkarte, direkt
> an den DAC und die andere Seite auf GND anschließen
Witzbold!

von minifloat (Gast)


Lesenswert?

Gendo I. schrieb:
> hat das 16bit wave file, welches ich mit audacity exportiert habe, plus
> und minus? - kann ich das wavefile in ein uint16 array einlesen oder
> muss es in ein int16?

Es hat Plus und Minus, daher signed.
Für die Ausgabe muss es noch nach oben geschoben werden.

int16_t array[LAENGE]

ausgabe = ((int32_t)array[position] + 32768L) >> 4

mfg mf

von Joachim B. (jar)


Lesenswert?

minifloat schrieb:
> Es hat Plus und Minus, daher signed.

ich habe auch schon anderes gesehen, OK hat dann einen DC Pegel der aber 
oft durch Koppelkondensatoren auch getrennt wird, nur eben nicht 
überall.

von Bernd (Gast)


Lesenswert?

Gendo I. schrieb:
> - Kann man überhaupt den Lautsprecher, von eine Audiogrußkarte, direkt
> an den DAC und die andere Seite auf GND anschließen
Ja. Wobei ein Kondensator als DC-Blocker und ggf. ein kleiner 
Vorwiderstand (ca. 10 bis 50 Ohm) nicht schaden:

http://elm-chan.org/works/sd8p/rc/sd8p_mo.png
http://elm-chan.org/works/mxb/mg.png

von Mark S. (voltwide)


Lesenswert?

Es gibt einen Unterschied zwischen einem DAC-Ausgang und einem Attiny 
Port Pin. Finde Ihn!

von MaWin (Gast)


Lesenswert?

Gendo I. schrieb:
> Jetzt meine Fragen:
>
> - ist es Richtig den Trigger timer, welcher die 12bit in das
> Ausgaberegister schiebt auf der Samplingrate der Audiofiles laufen zu
> lassen, also 48kHz in diesem Fall

Ja.

> - Kann man überhaupt den Lautsprecher, von eine Audiogrußkarte, direkt
> an den DAC und die andere Seite auf GND anschließen

Wird halt nicht laut.

> - hat das 16bit wave file, welches ich mit audacity exportiert habe,
> plus und minus? - kann ich das wavefile in ein uint16 array einlesen
> oder muss es in ein int16?

Ja. Es muss 2048 addiert werden nach der Umwandlung in 12 bit.

von Joachim B. (jar)


Lesenswert?

Gendo I. schrieb:
> Der DMA übergibt 12 MSBit in das DAC Register
> und mittels Timer trigger welcher auf 48kHz läuft wird der 12bit Wert in
> das Ausgaberegister gegeben.

wundert mich auch was der Tiny da soll!

von Klaus (Gast)


Lesenswert?

Pass aber auf das beim 16bit auf 12bit wandeln das vorzeigen noch passt, 
sonst klingt das nicht so gut.

von W.S. (Gast)


Lesenswert?

Gendo I. schrieb:
> - hat das 16bit wave file, welches ich mit audacity exportiert habe,
> plus und minus?

Ja, mein Lieber, da bist du bereits auf der richtigen Spur. Also wirf 
mal nen Blick in die Definitionen zu .wav Dateien und dann ins Manual zu 
dem DAC in deinem µC. +/-32 K versus (0..4095)<<irgendwas.

Du müßtest deiner DMA das Rechnen mit Offsets beibringen.. ;-)

W.S.

von Jens W. (jensw)


Lesenswert?

Hallo Gendo,

das Problem hatte ich auch schon.
Zwar mit einem anderen Controller, aber gleiche Anwendung.

Das Problem ist, dass die Byteorder von deinen 16bit Werten im File 
anders ist, als du das für deinen DAC vielleicht erwartest.
Du musst das High- und Lowbyte drehen.

Natürlich zusätzlich zu den signed- und unsigned-, Offset- usw 
Geschichten.

Grüße, Jens

von Gebhard R. (Firma: Raich Gerätebau & Entwicklung) (geb)


Lesenswert?

Bevor man durch falsche Umwandlungen auf 12 Bit die lustigsten Fehler 
erzeugt, sollte man mal die Hardware testen. Vorschlag: erzeuge ein 
Sinussignal mit z.B. 400Hz und schau mal mit dem Oszi, ob das Signal 
auch so aus dem DAC Ausgang kommt. Danach teste deinen High End Woofer 
und erst dann lass dein Wavefile auf die arme CPU los.

Grüsse

von Stefan F. (Gast)


Lesenswert?

Falls du *.wav Dateien verwendest: Das sind keine RAW Files, sondern 
Container in denen alles Mögliche drin sein kann, genauer gesagt RIFF 
Streams.

von Bernd (Gast)


Lesenswert?

Mark S. schrieb:
> Es gibt einen Unterschied zwischen einem DAC-Ausgang und einem Attiny
> Port Pin. Finde Ihn!
Beim Tiny wird in den verlinkten Schaltplänen die High-Speed-PWM (64 
MHz) genommen. Von der Taktfrequenz bleiben am Ausgang 250 kHz über.

Ob ich den DAC-Ausgang des STM32 oder den schnellen PWM-Ausgang des Tiny 
verwende, spielt für einen Lautsprecher kein Rolle.
Ich muß dafür sorgen, das mit dem Sampletakt die Daten an der richtigen 
Stelle abgeladen werden, um am Ausgang eine 'analoge' Waveform zu 
bekommen.

Wo ist jetzt für die eigentliche Anwendung (=Soundausgabe) der 
Unterschied?


Gebhard R. schrieb:
> Vorschlag: erzeuge ein
> Sinussignal mit z.B. 400Hz und schau mal mit dem Oszi, ob das Signal
> auch so aus dem DAC Ausgang kommt.
Gute Idee! Man kann sich auch direkt im Controller einen Sägezahn 
erzeugen (einfacher Zähler). Damit kann man feststellen, ob die 
Soundausgabe oder Byteorder bzw. Offset das Problem sind.

von Gendo I. (gendoikari)


Lesenswert?

Hallo Hobbys und Profis,

LOL Troll.. und dann noch als Gast einloggen.

Ja wie jeder hier mit Arbeit und Familie komme ich zu meinem Hobby nur 
ab und zu am Wochenende. Schade, dass du das nicht kennst.

Zum zweiten. Ich weis sehr wohl, dass ein DAC keine Push/Pull Stufe ist. 
Die Frage bezog sich eher darauf, ob man vielleicht ein Spannungsteiler 
braucht.

Laut genug für einen Testaufbau ist es, wenn es mal gehen sollte 
natürlich dann an einen Vorverstärker und an eine Endstufe.

Na gut.

An alle anderen vielen Dank für die Ideen.


Ich habe mir eine Schleife programmiert, da es aber immer noch nicht 
richtig funktioniert.  Alle Varianten hier rumprobiert, leider ohne 
Erfolg. :(

Ein Sinusarray etc. hab ich alles schon ausgegeben und mit dem Oszi 
aufgenommen, dass geht ja alles. Das ist ja extrem einfach.



const uint16_t sine_wave_array[32] = {2047, 1648, 1264, 910, 600,  345,
                   156, 39,  0,  39,  156,  345,
                   600, 910, 1264, 1648, 2048, 2447,
                   2831, 3185, 3495, 3750, 3939, 4056,
                   4095, 4056, 3939, 3750, 3495, 3185,
                   2831, 2447};


 HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*) sine_wave_array, 
32, DAC_ALIGN_12B_R );
 HAL_TIM_Base_Start(&htim6);





Deshalb verstehe ich das Problem mit dem wave file nicht.

int16_t DAC_Buff[512];   // Der array 512


/* #####   Hier die der Ausschnitt wo ich eure ganzen Ideen und 
Vorschläge ausprobiert habe #### */

 f_read (&file,&DAC_Buff[0],512,&cnt);       //beider 256 Buffer 
befüllen


  for(uint16_t n=0; n<512;n++)
  {
    temp=((int32_t)DAC_Buff[n]+2048)>>4;  // offset auf array

         /* ##### high und low byte tauschen  #### */

         t1=temp&0xff00;
    t2=temp&0xff;
    temp=(t2<<8)+(t1>>8);

    DAC_Buff[n]=temp;      // Berechneten Wert zurück in Array schreiben
    temp=0;                // temporären Variable löschen

  }



Dann nur noch den DAC DMA und den Trigger Timer starten und los geht's.


 HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*) DAC_Buff, 512, 
DAC_ALIGN_12B_R );
 HAL_TIM_Base_Start(&htim6);

von Gendo I. (gendoikari)


Lesenswert?

Jens W. schrieb:
> Hallo Gendo,
>
> das Problem hatte ich auch schon.
> Zwar mit einem anderen Controller, aber gleiche Anwendung.
>
> Das Problem ist, dass die Byteorder von deinen 16bit Werten im File
> anders ist, als du das für deinen DAC vielleicht erwartest.
> Du musst das High- und Lowbyte drehen.
>
> Natürlich zusätzlich zu den signed- und unsigned-, Offset- usw
> Geschichten.
>
> Grüße, Jens


Das mit High- und Lowbyte drehen hab ich jetzt mal probiert, nur wir das 
mit dem  signed- und unsigned-, Offset- usw noch nicht richtig sein. 
Klingt immer noch komisch :D

von Dummbeutel (Gast)


Angehängte Dateien:

Lesenswert?

Im Anhang mal 1 Sekunde 600 Hz mit -1 dB ohne stoerende Header.

Viel Spass.

von Gendo I. (gendoikari)


Lesenswert?

Vielen Dank :)

Da kann ich das schon mal als Fehlerquelle ausschließen und noch mal die 
Register prüfen.

von Gendo I. (gendoikari)


Angehängte Dateien:

Lesenswert?

Dummbeutel schrieb:
> Im Anhang mal 1 Sekunde 600 Hz mit -1 dB ohne stoerende Header.
>
> Viel Spass.


Um den DMA auszuschließen und debuggen zu können, habe ich jetzt mal das 
RAW File manuell in das DAC hold Register geschoben. Die oberen 12bit 
landen auch wie gewollt mit TIM6 trigger im DOR1 Register.
Leider klingt es immer noch nicht. Daher habe ich mit das ganze mal im 
Oszi angeschaut. Es kommen immer nur 8 Werte und dann immer low, dann 
wieder 8 Werte. Siehe Anhang. Woher könnte das kommen? Ist mein DMA zu 
langsam der den File Stream bedient?








  res = f_open( &file, FileName, FA_READ );   //file oeffnen
    if(res) return 1;

     TIM6->CR1 |= TIM_CR1_CEN;
while(1)
{

   f_read (&file,&DAC_Buff[0],512,&cnt);       //beider 256 Buffer 
befüllen
   if(cnt<256)break;

    for(uint16_t n=0; n<512;n++)
    {
//      temp=((uint32_t)DAC_Buff[n]+0xFF);
//
//      t1=temp&0xff00;
//      t2=temp&0xff;
//      temp=(t2<<8)+(t1>>8);
//
//      DAC_Buff[n]=temp;
//      temp=0;
      DAC1->DHR12L1 = (DAC_Buff[n]);

     while(0== LL_TIM_IsActiveFlag_UPDATE(TIM6));

    }

}
    TIM6->CR1 &= ~TIM_CR1_CEN;

    f_close(&file);

von Gendo I. (gendoikari)


Angehängte Dateien:

Lesenswert?

Hab es noch mal mit der normalen DMA Funktion probiert. Jetzt habe ich 
ein 600MH z Funktion, aber in 4x 128byte Blöcken und aller 3Blöcken 
fehlt einer und die 3 die kommen sind unter einander vertauscht. Also 1 
und 3 gehören zusammen. Das kann man an dem Signalverlauf sehen.

Siehe Anhang.

Ich weiß nicht wo das mit den 128byte her kommt.

von Forist (Gast)


Lesenswert?

Kann ein Moderator vielleicht bitte mal den Titel korrigieren?
Das ist ja widerlich.

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.