Forum: Mikrocontroller und Digitale Elektronik Brauche kurz Hilfe bei MP3-Player


von Tobias P. (hubertus)


Lesenswert?

Hallo

angeregt durch einen anderen Thread, den ich hier mal gelesen habe, 
wollte ich auch einen eigenen MP3-Player bauen. Um zu testen, ob alles 
funktioniert, benutze ich das STM32F4 Discovery Board. Dort habe ich 
einen SD-Kartensockel angelötet. In meiner Software ist FATFS von 
ElmChan drin, sowie der Helix-Decoder.

Zuerst habe ich, um den Decoder zu testen, einfach eine kleine MP3-Datei 
als Array in den Flash des STM geladen und dann jeweils Stück für Stück 
in den RAM kopiert. Damit hat das Abspielen eines MP3 wunderbar 
geklappt, ohne Aussetzer oder so, selbst bei 48 kHz und 320 kBuit/s. 
Jetzt will ich das MP3-File allerdings von der SD-Karte lesen! Da ich 
später noch ein GUI implementieren will, habe ich mir gedacht, die SW 
als kleinen Zustandsautomaten zu implementierren. Hier mein main-Code:
1
__attribute__((noreturn)) void main(void)
2
{
3
   state_t state = init_play_mp3;
4
  int ind = 0;
5
  int remain_bytes;
6
  int free_samples;
7
  int bytes_to_read;
8
9
  int br;
10
  int filesize;
11
  memset(buf, 0, sizeof(buf));
12
  memset(sdbuf, 0, sizeof(sdbuf));
13
14
15
  init_hardware();
16
17
  mci_media_init();
18
19
20
  f_mount(&fs, "0:", 1);
21
22
23
24
25
26
  while(1)
27
  {
28
29
30
31
    switch(state)
32
    {
33
      case init_play_mp3:
34
      {
35
        init_mp3(buf, NUMOF_ELEMENTS(buf));
36
        state = preload_mp3_buffer;
37
38
        f_open(&fl, "0:/eminence_front.mp3", FA_READ);
39
          f_stat("0:/eminence_front.mp3", &fileinfo);
40
          filesize = fileinfo.fsize;
41
42
          ind = 0;
43
44
        break;
45
      }
46
47
      case preload_mp3_buffer:
48
      {
49
        int decoded_bytes;
50
51
        bytes_to_read = (filesize - ind) > BUFSZ ? BUFSZ : (filesize - ind);
52
53
        f_lseek(&fl, ind);
54
        f_read(&fl, sdbuf, bytes_to_read, &br);
55
56
57
        remain_bytes = decode_mp3(sdbuf, bytes_to_read);
58
        decoded_bytes = bytes_to_read - remain_bytes;
59
60
        ind = ind + decoded_bytes;
61
62
        free_samples = get_free_samps();
63
64
65
        if(free_samples < 4608)
66
        {
67
          start_playback();
68
          state = play_mp3;
69
        }
70
71
        break;
72
      }
73
74
      case play_mp3:
75
      {
76
77
        int prev_remain_bytes = 0;
78
        int decoded_bytes;
79
80
        free_samples = get_free_samps();
81
        if(free_samples > 2304*1)
82
        {
83
84
85
86
          GPIOC_BSRR = BIT_05;
87
          prev_remain_bytes = remain_bytes;
88
89
          remain_bytes = decode_mp3(&sdbuf[sizeof(sdbuf)-remain_bytes], remain_bytes);
90
          decoded_bytes = prev_remain_bytes - remain_bytes;
91
          ind = ind + decoded_bytes;
92
93
          GPIOC_BSRR = BIT_21;
94
        }
95
96
97
        if((remain_bytes < 512) || (decoded_bytes == 0))
98
        {
99
100
          GPIOD_BSRR = BIT_12;
101
          bytes_to_read = (filesize - ind) > BUFSZ ? BUFSZ : (filesize - ind);
102
103
          if(bytes_to_read < 100)
104
          {
105
            stop_playback();
106
            state = stop_mp3;
107
            break;
108
          }
109
          f_lseek(&fl, ind);
110
          f_read(&fl, sdbuf, bytes_to_read, &br);
111
112
          remain_bytes = bytes_to_read;
113
114
          GPIOD_BSRR = BIT_28;
115
        }
116
117
118
119
        break;
120
      }
121
122
      case stop_mp3:
123
      {
124
        free_mp3();
125
        state = init_play_mp3;
126
        ind = 0;
127
        break;
128
      }
129
    }
130
  }
131
}


Jetzt stelle ich allerdings fest, dass es gelegentlich zu kleinen 
Aussetzern kommt. Da alles funktioniert, wenn ich die Datei per memcpy() 
aus dem Flash kopiere und so decodieren, muss das Problem am 
Buffer-Management zusammen mit dem Lesen der SD-Karte zusammenhängen. 
Leider sehe ich gerade nicht, wo man was optimieren müsste. Wäre es 
möglich dass die Profis hier mal kurz auf meinen Code schauen? :-)

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.