summaryrefslogtreecommitdiff
path: root/apps/plugins/mpegplayer/pcm_output.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/mpegplayer/pcm_output.c')
-rw-r--r--apps/plugins/mpegplayer/pcm_output.c35
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;
33static struct pcm_frame_header * ALIGNED_ATTR(4) pcmbuf_tail IBSS_ATTR; 33static struct pcm_frame_header * ALIGNED_ATTR(4) pcmbuf_tail IBSS_ATTR;
34 34
35/* Bytes */ 35/* Bytes */
36static ssize_t pcmbuf_curr_size IBSS_ATTR; /* Size of currently playing frame */
36static uint64_t pcmbuf_read IBSS_ATTR; /* Number of bytes read by DMA */ 37static uint64_t pcmbuf_read IBSS_ATTR; /* Number of bytes read by DMA */
37static uint64_t pcmbuf_written IBSS_ATTR; /* Number of bytes written by source */ 38static uint64_t pcmbuf_written IBSS_ATTR; /* Number of bytes written by source */
38static ssize_t pcmbuf_threshold IBSS_ATTR; /* Non-silence threshold */ 39static ssize_t pcmbuf_threshold IBSS_ATTR; /* Non-silence threshold */
@@ -42,6 +43,9 @@ static uint32_t clock_base IBSS_ATTR; /* Our base clock */
42static uint32_t clock_start IBSS_ATTR; /* Clock at playback start */ 43static uint32_t clock_start IBSS_ATTR; /* Clock at playback start */
43static int32_t clock_adjust IBSS_ATTR; /* Clock drift adjustment */ 44static int32_t clock_adjust IBSS_ATTR; /* Clock drift adjustment */
44 45
46int pcm_skipped = 0;
47int pcm_underruns = 0;
48
45/* Small silence clip. ~5.80ms @ 44.1kHz */ 49/* Small silence clip. ~5.80ms @ 44.1kHz */
46static int16_t silence[256*2] ALIGNED_ATTR(4) = { 0 }; 50static 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 */
69static void get_more(unsigned char **start, size_t *size) 73static 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)