Forum: Mikrocontroller und Digitale Elektronik Wav mit Atmega in 16bit 44,1kHz ?


von Sven W. (sven_w18)


Lesenswert?

Hallo !

Ich habe einen funktionierenden Wav-Player mit einem Atmega168 
aufgebaut. Ich bin aber mit der Soundqualität nicht so wirklich 
zufrieden. Die Ausgabe mache ich über fast-PWM, kriege es aber einfach 
nicht hin, den 16-Bit Timer richtig zu füttern um eine 16bit Datei 
abzuspielen.

Der Code ist zum Teil abgeschaut, so in voller Gänze habe ich die Timer 
noch nicht verstanden.
Kann mir bitte jemand helfen ?
1
...
2
#define SAMPLERATE   44100
3
#define BUFLEN    512  
4
#define NBLOCKS    2
5
#define BLOCKLEN    (unsigned int)(BUFLEN/NBLOCKS)
6
...
7
ISR(TIMER1_OVF_vect)
8
{
9
  unsigned int i;
10
11
  i=*rptr++;
12
  OCR1A = i + (i>>1)+33;
13
  i=*rptr++;
14
  OCR1B = i + (i>>1)+33;
15
16
  if(rptr==buf0+BUFLEN)
17
    rptr=buf0;
18
19
  for(i=0;i<NBLOCKS;i++)
20
    if(rptr==buf0+i*BLOCKLEN)
21
      blockstowrite++;
22
}
23
24
void wiedergabe(struct fat16_file_struct* fd)
25
{
26
      fat16_read_file(fd, (uint8_t*)buf0, BUFLEN);
27
      wptr=rptr=buf0;
28
      //rptr+=44;              //skip WAV header
29
      blockstowrite=0;
30
      //status=PLAY;
31
      sei();
32
}
33
34
void dateiende(struct fat16_file_struct* fd)
35
{
36
  int32_t file_pos = 0;
37
  
38
  if(fat16_read_file(fd, (uint8_t*)wptr, BLOCKLEN)<BLOCKLEN)
39
        {
40
          cli();
41
          fat16_seek_file(fd, &file_pos, FAT16_SEEK_SET);
42
          //fat16_close_file(fd);
43
          status=START;
44
        }
45
        else
46
        {
47
          wptr+=BLOCKLEN;
48
          if(wptr==buf0+BUFLEN) wptr=buf0;
49
          blockstowrite--;
50
        }
51
}
52
53
int main()
54
{
55
  ...
56
         ...
57
58
59
//  ICR1   = (F_CPU/SAMPLERATE);       
60
 ICR1   = 451;
61
62
  TCCR1A = (1<<COM1A1) | (1<<COM1B1) | (1<<WGM11); //
63
  TCCR1B = (1<<WGM12) | (1<<WGM13) | (1<<CS10);
64
  TIMSK1 = (1<<TOIE1);
65
66
  TCCR0A = (1<<COM0A0)|(1<<COM0B0)|(1<<WGM01);
67
  TCCR0B = (1<<CS00);   // F_CPU
68
69
  OCR0A=OCR1A=225;
70
  OCR0B=OCR1B=225;
71
72
...
73
...

von Gerd M. (avrgerd)


Lesenswert?

Wenn Dein Atmega 24Mhz hat und Du ein Signal mit 16bit Auflösung der PWM 
ausgeben willst, dann schaffts Du max. nur 366Hz und nicht 44.1kHz.

Kann also nicht gehen!

Gruss,
avrGerd

von Sven W. (sven_w18)


Lesenswert?

Wie berechnest du diese Frequenz ?
Mein Atmega läuft mit 20MHz.

von Richard J. (eltentakel)


Lesenswert?

Ansich ist es ganz einfach:

du musst die 20Mhz einfach mal durch 2^16 teilen, da ergibt sich maximal
306 Hz. Ich empfehle eine deutlich geringere Auflösung zu verwenden. bei
10 bit sinds immerhin noch 20khz.

von spess53 (Gast)


Lesenswert?

Hi

>Wie berechnest du diese Frequenz ?
>Mein Atmega läuft mit 20MHz.

Bei dir:  20MHz/65536=305,1758Hz

Du must dich entscheiden. Entweder 16Bit oder 44,1kHz.

>bei 10 bit sinds immerhin noch 20khz.

Oder 9Bit/44,1KHz bei 22,1184MHz.

MfG Spess

von Sven W. (sven_w18)


Lesenswert?

Ahhhh...

so langsam fällt der Groschen.

War jetzt auf dem Holzweg... das 16bit doppelt so viel wie 8bit sind...
aber das ist ja expotentiell... Anfägerfehler

von spess53 (Gast)


Lesenswert?

Hi

>Gut, dadurch, dass es ein 8 bit Prozessor ist und ich 16 bit
>benutzen will:

Das hat nichts mit 8-Bit-Controller zu tun. Wenn du eine Auflösung von 
16 Bit haben willst brauchst du auch eine 16-Bit PWM. In deinem Programm 
hat die PWM eine Auflösung von etwa 8,8 Bit.

MfG Spess

von Sven W. (sven_w18)


Lesenswert?

Machen 10Bit/20kHz einen Qualitätsunterschied zu 8Bit/44,1kHz ?

Und vor allem mit welchen Programm kann ich eine wav Datei so verändern?
(Die meisten bieten nur den Standart an: 8/16, 22,05/44,1)

von Peter II (Gast)


Lesenswert?

Sven W. schrieb:
> Und vor allem mit welchen Programm kann ich eine wav Datei so verändern?

wozu ändern? kann man doch beim auslesen einfach umrechen.

von Sven W. (sven_w18)


Angehängte Dateien:

Lesenswert?

Hi Spess

der Atmega168 hat doch einen 16-bit PWM ???

von Sven W. (sven_w18)


Lesenswert?

Hi Peter II !

Wie rechne ich das im Programm um ??? und wo?

von spess53 (Gast)


Lesenswert?

Hi

>der Atmega168 hat doch einen 16-bit PWM ???

Ja, mit ICR=65535 wären es 16 Bit. Aber mit ICR1=451 hast du nur noch 
die erwähnten 8,8Bit.

MfG Spess

von Peter II (Gast)


Lesenswert?

Sven W. schrieb:
> Wie rechne ich das im Programm um ??? und wo?

hast du das Programm geschrieben oder nur kopiert?

> i=*rptr++;
i = i >> 6;
> OCR1A = i + (i>>1)+33;

schon wird eine 16bit datei als 10bit ausgegeben (PWM muss aber noch 
angepasst werden)

von Sven W. (sven_w18)


Lesenswert?

Peter II schrieb:
> Sven W. schrieb:
>> Wie rechne ich das im Programm um ??? und wo?
>
> hast du das Programm geschrieben oder nur kopiert?

Teilsweise kopiert, aber auch viel selbst ausgedacht.
Wie schon gesagt, das mit den Timern und PWM habe ich noch nicht so ganz 
verstanden - also das zusammenspiel der beiden.

>
>> i=*rptr++;
> i = i >> 6;
>> OCR1A = i + (i>>1)+33;

Danke für den Tipp. (Bitverschiebung, eigendlich ganz logisch...)

>
> schon wird eine 16bit datei als 10bit ausgegeben (PWM muss aber noch
> angepasst werden)

von Sven W. (sven_w18)


Lesenswert?

spess53 schrieb:

> Ja, mit ICR=65535 wären es 16 Bit. Aber mit ICR1=451 hast du nur noch
> die erwähnten 8,8Bit.

Das bedeutet: 16Bit, mono, 44,1khz Wav-Dateien funktionieren dann mit 
meinem Programm ? Oder sind da noch andere Anpassungen zu machen ?
z.B. bei den OCRxx Registern ?

Gibt es eigendlich ein gutes Buch zum Thema Atmega ?

von Sven W. (sven_w18)


Lesenswert?

> Ja, mit ICR=65535 wären es 16 Bit. Aber mit ICR1=451 hast du nur noch
> die erwähnten 8,8Bit.

Ich habe darüber gerade mal (versucht) nachzudenken.
Die 451 resultiren ja aus der Rechnung CPU-Takt / 44.1kHz.
Nach meinem Verständnis heißt das:
Nach 451 Zählern (Takten) löse Interrupt aus und führe Routine 
ISR(TIMER1_OVF_vect)aus, also lade Register für PWM neu.

Mit ICR1=451 441000 mal die Sekunde
Mit ICR1=65535 305 mal die Sekunde

Oder????

Aber ich will doch alle 451 Takte mein Register neu laden. nur muss ich 
jetzt den 16 Bit PWM laden und da weiß ich nicht wie.

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.