diff options
Diffstat (limited to 'apps/plugins/mpegplayer/pcm_output.c')
-rw-r--r-- | apps/plugins/mpegplayer/pcm_output.c | 35 |
1 files changed, 26 insertions, 9 deletions
diff --git a/apps/plugins/mpegplayer/pcm_output.c b/apps/plugins/mpegplayer/pcm_output.c index ac89308af1..e17f635f72 100644 --- a/apps/plugins/mpegplayer/pcm_output.c +++ b/apps/plugins/mpegplayer/pcm_output.c | |||
@@ -33,6 +33,7 @@ static struct pcm_frame_header * ALIGNED_ATTR(4) pcmbuf_head IBSS_ATTR; | |||
33 | static struct pcm_frame_header * ALIGNED_ATTR(4) pcmbuf_tail IBSS_ATTR; | 33 | static struct pcm_frame_header * ALIGNED_ATTR(4) pcmbuf_tail IBSS_ATTR; |
34 | 34 | ||
35 | /* Bytes */ | 35 | /* Bytes */ |
36 | static ssize_t pcmbuf_curr_size IBSS_ATTR; /* Size of currently playing frame */ | ||
36 | static uint64_t pcmbuf_read IBSS_ATTR; /* Number of bytes read by DMA */ | 37 | static uint64_t pcmbuf_read IBSS_ATTR; /* Number of bytes read by DMA */ |
37 | static uint64_t pcmbuf_written IBSS_ATTR; /* Number of bytes written by source */ | 38 | static uint64_t pcmbuf_written IBSS_ATTR; /* Number of bytes written by source */ |
38 | static ssize_t pcmbuf_threshold IBSS_ATTR; /* Non-silence threshold */ | 39 | static ssize_t pcmbuf_threshold IBSS_ATTR; /* Non-silence threshold */ |
@@ -42,6 +43,9 @@ static uint32_t clock_base IBSS_ATTR; /* Our base clock */ | |||
42 | static uint32_t clock_start IBSS_ATTR; /* Clock at playback start */ | 43 | static uint32_t clock_start IBSS_ATTR; /* Clock at playback start */ |
43 | static int32_t clock_adjust IBSS_ATTR; /* Clock drift adjustment */ | 44 | static int32_t clock_adjust IBSS_ATTR; /* Clock drift adjustment */ |
44 | 45 | ||
46 | int pcm_skipped = 0; | ||
47 | int pcm_underruns = 0; | ||
48 | |||
45 | /* Small silence clip. ~5.80ms @ 44.1kHz */ | 49 | /* Small silence clip. ~5.80ms @ 44.1kHz */ |
46 | static int16_t silence[256*2] ALIGNED_ATTR(4) = { 0 }; | 50 | static int16_t silence[256*2] ALIGNED_ATTR(4) = { 0 }; |
47 | 51 | ||
@@ -51,7 +55,7 @@ static inline void pcm_advance_buffer(struct pcm_frame_header **p, | |||
51 | { | 55 | { |
52 | *p = SKIPBYTES(*p, size); | 56 | *p = SKIPBYTES(*p, size); |
53 | if (*p >= pcmbuf_end) | 57 | if (*p >= pcmbuf_end) |
54 | *p = pcm_buffer; | 58 | *p = SKIPBYTES(*p, -PCMOUT_BUFSIZE); |
55 | } | 59 | } |
56 | 60 | ||
57 | /* Inline internally but not externally */ | 61 | /* Inline internally but not externally */ |
@@ -68,7 +72,13 @@ inline ssize_t pcm_output_free(void) | |||
68 | /* Audio DMA handler */ | 72 | /* Audio DMA handler */ |
69 | static void get_more(unsigned char **start, size_t *size) | 73 | static void get_more(unsigned char **start, size_t *size) |
70 | { | 74 | { |
71 | ssize_t sz = pcm_output_used(); | 75 | ssize_t sz; |
76 | |||
77 | /* Free-up the last frame played frame if any */ | ||
78 | pcmbuf_read += pcmbuf_curr_size; | ||
79 | pcmbuf_curr_size = 0; | ||
80 | |||
81 | sz = pcm_output_used(); | ||
72 | 82 | ||
73 | if (sz > pcmbuf_threshold) | 83 | if (sz > pcmbuf_threshold) |
74 | { | 84 | { |
@@ -95,16 +105,20 @@ static void get_more(unsigned char **start, size_t *size) | |||
95 | /* Frame more than 100ms late - drop it */ | 105 | /* Frame more than 100ms late - drop it */ |
96 | pcm_advance_buffer(&pcmbuf_head, sz); | 106 | pcm_advance_buffer(&pcmbuf_head, sz); |
97 | pcmbuf_read += sz; | 107 | pcmbuf_read += sz; |
108 | pcm_skipped++; | ||
98 | if (pcmbuf_read < pcmbuf_written) | 109 | if (pcmbuf_read < pcmbuf_written) |
99 | continue; | 110 | continue; |
111 | |||
112 | /* Ran out so revert to default watermark */ | ||
113 | pcmbuf_threshold = PCMOUT_PLAY_WM; | ||
100 | } | 114 | } |
101 | else if (offset < 100*CLOCK_RATE/1000) | 115 | else if (offset < 100*CLOCK_RATE/1000) |
102 | { | 116 | { |
103 | /* Frame less than 100ms early - play it */ | 117 | /* Frame less than 100ms early - play it */ |
104 | *start = (unsigned char *)pcmbuf_head->data; | 118 | *start = pcmbuf_head->data; |
105 | 119 | ||
106 | pcm_advance_buffer(&pcmbuf_head, sz); | 120 | pcm_advance_buffer(&pcmbuf_head, sz); |
107 | pcmbuf_read += sz; | 121 | pcmbuf_curr_size = sz; |
108 | 122 | ||
109 | sz -= sizeof (struct pcm_frame_header); | 123 | sz -= sizeof (struct pcm_frame_header); |
110 | 124 | ||
@@ -124,6 +138,9 @@ static void get_more(unsigned char **start, size_t *size) | |||
124 | else | 138 | else |
125 | { | 139 | { |
126 | /* Ran out so revert to default watermark */ | 140 | /* Ran out so revert to default watermark */ |
141 | if (pcmbuf_threshold == PCMOUT_LOW_WM) | ||
142 | pcm_underruns++; | ||
143 | |||
127 | pcmbuf_threshold = PCMOUT_PLAY_WM; | 144 | pcmbuf_threshold = PCMOUT_PLAY_WM; |
128 | } | 145 | } |
129 | 146 | ||
@@ -164,8 +181,9 @@ void pcm_output_flush(void) | |||
164 | rb->pcm_play_stop(); | 181 | rb->pcm_play_stop(); |
165 | 182 | ||
166 | pcmbuf_threshold = PCMOUT_PLAY_WM; | 183 | pcmbuf_threshold = PCMOUT_PLAY_WM; |
167 | pcmbuf_read = pcmbuf_written = 0; | 184 | pcmbuf_curr_size = pcmbuf_read = pcmbuf_written = 0; |
168 | pcmbuf_head = pcmbuf_tail = pcm_buffer; | 185 | pcmbuf_head = pcmbuf_tail = pcm_buffer; |
186 | pcm_skipped = pcm_underruns = 0; | ||
169 | 187 | ||
170 | /* Restart if playing state was current */ | 188 | /* Restart if playing state was current */ |
171 | if (playing && !paused) | 189 | if (playing && !paused) |
@@ -251,10 +269,9 @@ bool pcm_output_init(void) | |||
251 | pcmbuf_head = pcm_buffer; | 269 | pcmbuf_head = pcm_buffer; |
252 | pcmbuf_tail = pcm_buffer; | 270 | pcmbuf_tail = pcm_buffer; |
253 | pcmbuf_end = SKIPBYTES(pcm_buffer, PCMOUT_BUFSIZE); | 271 | pcmbuf_end = SKIPBYTES(pcm_buffer, PCMOUT_BUFSIZE); |
254 | pcmbuf_read = 0; | 272 | pcmbuf_curr_size = pcmbuf_read = pcmbuf_written = 0; |
255 | pcmbuf_written = 0; | ||
256 | 273 | ||
257 | rb->pcm_set_frequency(SAMPR_44); | 274 | rb->pcm_set_frequency(NATIVE_FREQUENCY); |
258 | 275 | ||
259 | #if INPUT_SRC_CAPS != 0 | 276 | #if INPUT_SRC_CAPS != 0 |
260 | /* Select playback */ | 277 | /* Select playback */ |
@@ -264,7 +281,7 @@ bool pcm_output_init(void) | |||
264 | 281 | ||
265 | #if SILENCE_TEST_TONE | 282 | #if SILENCE_TEST_TONE |
266 | /* Make the silence clip a square wave */ | 283 | /* Make the silence clip a square wave */ |
267 | const int16_t silence_amp = 32767 / 16; | 284 | const int16_t silence_amp = INT16_MAX / 16; |
268 | unsigned i; | 285 | unsigned i; |
269 | 286 | ||
270 | for (i = 0; i < ARRAYLEN(silence); i += 2) | 287 | for (i = 0; i < ARRAYLEN(silence); i += 2) |