Wav mit Atmega in 16bit 44,1kHz ?

#2748931
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
...
Gast #2749435
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
Gast #2749446
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
#2751798
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)
#2751804
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren