Forum: Mikrocontroller und Digitale Elektronik AVR pwm-Audio knacken


von Uli W. (superhuey)


Lesenswert?

Liebe Forengemeinde,

die Verweiflung ist groß, aber die Hoffnung lebt noch...

Ich habe Probleme mit meinem Soundmodul für mein Modellfahrzeug.
Da ich so einige Wave-Dateien abspiele, die ich nicht in den
verwendeten ATmega1284P bekomme, habe ich mich dazu entschlossen,
das Modul mit einer SD-Karte auszustatten. Um die Stille beim Laden
des nächsten Sounds zu überbrücken, gibt es ein zweites Modul
gleicher Bauart. Die Module arbeiten nach dem Prinzip Master-Slave
und es wird kurz vor Ende einer Datei auf das andere Modul umgeschaltet.

Das Problem besteht darin, das beim Apspielen eines Sounds ein nerviges
Knackgeräusch vorausgeht. Die Dateien sind alle im gleichen Format 
(8bit, 22050Hz,Mono) und sind sauber geschnitten.

Zum Einsatz kommt AVR-DOS (V5.5).

Vieles habe ich schon ausprobiert, aber leider alles ohne den 
entsprechenden
Erfolg.

Mit der bitte um Hilfe

Ulrich


Code Auszug:
1
'----------------------------------------------------------------------------
2
'WAVEPLAYER PLAYWAVEFILE
3
'----------------------------------------------------------------------------
4
Sub PlayWaveFile(WP_FILENAME as string)
5
6
   open WP_FILENAME For Binary As #SD_FF
7
8
   WP_lx = _XTAL / WP_SampleRate                                                 ' CPU Speed / SampleRate of wave file
9
   WP_lx = WP_lx - 1
10
   Compare1a = WP_lx
11
12
   WP_lx = 2 : seek #10 , WP_lx
13
14
   ''' start loading buffers
15
   get #SD_FF , WP_BUF_A(1) , , WP_BUFSIZE                                       ' preload buffer A
16
   WP_A_BUF_STATUS = WP_BUFFULL                                                  ' mark buffer A as full
17
   get #SD_FF , WP_BUF_B(1) , , WP_BUFSIZE                                       ' preload buffer B
18
   WP_B_Buf_Status = WP_BUFFULL                                                  ' mark buffer B as full
19
   WP_ActiveBuffer = WP_BUFA                                                     ' start with buf 0
20
   WP_BUFPos = 0                                                                 ' Reset the buffer possition
21
22
   '======[ start playing file!!! ]============================
23
   'Start Timer1
24
   'Start Timer2
25
   'Enable Compare1a
26
   'DDRD.6 = 1 : DDRD.7 = 1
27
   'PORTD.6 = 1 : PORTD.7 = 1
28
29
   ''' Watch the two buffers and fill them up when ether is empty
30
   while Eof(#SD_FF) = 0
31
      if WP_A_BUF_STATUS = WP_BUFEMPTY then
32
         get #SD_FF , WP_BUF_A(1) , , WP_BUFSIZE
33
         WP_A_BUF_STATUS = WP_BUFFULL
34
         FILENEXT2 = FILENEXT2 + 250
35
      elseif WP_B_Buf_Status = WP_BUFEMPTY then
36
         get #SD_FF , WP_BUF_B(1) , , WP_BUFSIZE
37
         WP_B_Buf_Status = WP_BUFFULL
38
         FILENEXT2 = FILENEXT2 + 250
39
      else
40
         ' Both buffers are full here so this would be a good place to
41
         ' do some other stuff if needed.  DON'T TAKE TOO LONG THOUGH! ;)
42
         'if P_STATUS = 0 then
43
         '   Start Timer1
44
         '   Start Timer2
45
         '   Enable Compare1a
46
         '   P_STATUS = 1
47
         '   PORTD.6 = 0
48
         'end if
49
         P_STATUS = 1
50
         if FILENEXT2 >= FILENEXT1 then : LBLL = 1 : SIGNAL_OUT = 1 : end if
51
      end if
52
   wend
53
   'DDRD.6 = 0 : DDRD.7 = 0
54
   'PORTD.6 = 0 : PORTD.7 = 0
55
   P_STATUS = 0
56
   PWM2A = 128
57
   PWM2B = 128
58
   'Disable Compare1a
59
   'Stop Timer1
60
   'Stop Timer2
61
   close #SD_FF
62
63
End Sub
64
65
66
'----------------------------------------------------------------------------
67
'WAVEPLAYER WP_PLAY_ISR
68
'----------------------------------------------------------------------------
69
WP_Play_isr:
70
   if P_STATUS = 1 then
71
      if WP_ActiveBuffer = WP_BUFA then                                          ' buffer A
72
         incr WP_BUFPos                                                          ' incrment to next byte
73
         Pwm2a = WP_BUF_A(WP_BUFPos)                                             ' load sample into pwm2a
74
         Pwm2b = WP_BUF_A(WP_BUFPos)                                             ' load same sample if mono
75
         if WP_BUFPos = WP_BUFSIZE then                                          ' hit end of buffer A
76
            WP_BUFPos = 0                                                        ' reset buffer pos to 0
77
            WP_ActiveBuffer = WP_BUFB                                            ' Set active buffer to B
78
            WP_A_BUF_STATUS = WP_BUFEMPTY                                        ' set buffer status empty
79
         end if
80
      else                                                                       ' buffer B
81
         incr WP_BUFPos                                                          ' incrment to next byte
82
         Pwm2a = WP_BUF_B(WP_BUFPos)                                             ' load sample into pwm2a
83
         Pwm2b = WP_BUF_B(WP_BUFPos)                                             ' load same sample if mono
84
         if WP_BUFPos = WP_BUFSIZE then                                          ' hit end of buffer A
85
            WP_BUFPos = 0                                                        ' reset buffer pos to 0
86
            WP_ActiveBuffer = WP_BUFA                                            ' Set active buffer to B
87
            WP_B_Buf_Status = WP_BUFEMPTY                                        ' set buffer status empty
88
         end if
89
      end if
90
   end if
91
Return

von Flip B. (frickelfreak)


Lesenswert?

Wie wäre es, statt immer neue Probleme zu flicken, lieber auf ein system 
zu wechseln, welches erstmal grundsätzlich für die Aufgabe geeignet ist.

von Peter D. (peda)


Lesenswert?

Uli W. schrieb:
> Das Problem besteht darin, das beim Apspielen eines Sounds ein nerviges
> Knackgeräusch vorausgeht.

Du darfst natürlich den Timer nicht abschalten, sondern mußt die PWM mit 
U/2 weiter laufen lassen.

von Jim M. (turboj)


Lesenswert?

Du könntest auch mal Pwm2a und Pwm2b vor dem Start des Timers auf 128 
setzen.

Edit: Blödsinn. Man muss den Pegel langsam von Ruhepegel auf Mitte 
(128) erhöhen (oder verringern) damit es nicht knackt. D.h. Du brauchst 
sowas wie eine Einschaltsequenz.

: Bearbeitet durch User
von Sascha (Gast)


Lesenswert?

Jim M. schrieb:
> Du könntest auch mal Pwm2a und Pwm2b vor dem Start des Timers auf
> 128
> setzen.
>
> Edit: Blödsinn. Man muss den Pegel langsam von Ruhepegel auf Mitte
> (128) erhöhen (oder verringern) damit es nicht knackt. D.h. Du brauchst
> sowas wie eine Einschaltsequenz.

Durch nen FIR laufen lassen.

von Uli W. (superhuey)


Lesenswert?

Hallo.

Vielen Dank für eure Anregungen, die mir bei der Lösung
geholfen haben.

Timer werden nicht mehr abgeschaltet und die PWM (=128) läuft
nun weiter.
Fazit: Das Knacken ist weg :)

Allen Dateien wurden die Header entfernt, damit nur die reinen
Daten gelesen werden müssen. Die Dateiinfos werden nach Boot
des uC von der SDKarte eingelesen. Hier benötige ich nur die
Dateigröße, alle anderen Infos sind Festwerte. Dies spart eine Menge
Zeit beim Einlesen.

Die Idee mit dem Filter war nicht schlecht. Das Knacken war weg,
der Sound war aber extrem verzerrt.

Nochmals vielen Dank.

Gruss
Ulrich

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.