summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2006-01-22 10:25:07 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2006-01-22 10:25:07 +0000
commit6d6ca6b6a5641a0ab3657e60a1770a440cc52493 (patch)
treead769586634236732aff30337e6b6465f1dad0c0
parent998610ca0bb8d12376936308631a8bed2f5e1281 (diff)
downloadrockbox-6d6ca6b6a5641a0ab3657e60a1770a440cc52493.tar.gz
rockbox-6d6ca6b6a5641a0ab3657e60a1770a440cc52493.zip
Muting trick to prevent tiny pops and glitchless mp3 seeking.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8416 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/codecs/mpa.c35
-rw-r--r--apps/pcmbuf.c31
-rw-r--r--apps/playback.c8
-rw-r--r--firmware/export/pcm_playback.h1
-rw-r--r--firmware/pcm_playback.c24
5 files changed, 62 insertions, 37 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c
index 2c946f3f0d..1be6222ccf 100644
--- a/apps/codecs/mpa.c
+++ b/apps/codecs/mpa.c
@@ -72,6 +72,22 @@ void recalc_samplecount(void)
72 samplecount -= start_skip + stop_skip; 72 samplecount -= start_skip + stop_skip;
73} 73}
74 74
75void init_mad(void)
76{
77 ci->memset(&stream, 0, sizeof(struct mad_stream));
78 ci->memset(&frame, 0, sizeof(struct mad_frame));
79 ci->memset(&synth, 0, sizeof(struct mad_synth));
80
81 mad_stream_init(&stream);
82 mad_frame_init(&frame);
83 mad_synth_init(&synth);
84
85 /* We do this so libmad doesn't try to call codec_calloc() */
86 ci->memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap));
87 frame.overlap = &mad_frame_overlap;
88 stream.main_data = &mad_main_data;
89}
90
75/* this is the codec entry point */ 91/* this is the codec entry point */
76enum codec_status codec_start(struct codec_api *api) 92enum codec_status codec_start(struct codec_api *api)
77{ 93{
@@ -107,18 +123,7 @@ enum codec_status codec_start(struct codec_api *api)
107 * Reinitializing seems to be necessary to avoid playback quircks when seeking. */ 123 * Reinitializing seems to be necessary to avoid playback quircks when seeking. */
108 next_track: 124 next_track:
109 125
110 ci->memset(&stream, 0, sizeof(struct mad_stream)); 126 init_mad();
111 ci->memset(&frame, 0, sizeof(struct mad_frame));
112 ci->memset(&synth, 0, sizeof(struct mad_synth));
113
114 mad_stream_init(&stream);
115 mad_frame_init(&frame);
116 mad_synth_init(&synth);
117
118 /* We do this so libmad doesn't try to call codec_calloc() */
119 ci->memset(mad_frame_overlap, 0, sizeof(mad_frame_overlap));
120 frame.overlap = &mad_frame_overlap;
121 stream.main_data = &mad_main_data;
122 127
123 file_end = 0; 128 file_end = 0;
124 while (!*ci->taginfo_ready && !ci->stop_codec) 129 while (!*ci->taginfo_ready && !ci->stop_codec)
@@ -168,11 +173,7 @@ enum codec_status codec_start(struct codec_api *api)
168 if (!ci->seek_buffer(newpos)) 173 if (!ci->seek_buffer(newpos))
169 goto next_track; 174 goto next_track;
170 ci->seek_complete(); 175 ci->seek_complete();
171 if (newpos == 0) 176 init_mad();
172 {
173 ci->id3->elapsed = 0;
174 goto next_track;
175 }
176 } 177 }
177 178
178 /* Lock buffers */ 179 /* Lock buffers */
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c
index fc58d9ccb3..e21f735bbb 100644
--- a/apps/pcmbuf.c
+++ b/apps/pcmbuf.c
@@ -60,6 +60,8 @@ static bool crossfade_init;
60static int crossfade_pos; 60static int crossfade_pos;
61static int crossfade_rem; 61static int crossfade_rem;
62 62
63static struct mutex pcmbuf_mutex;
64
63/* Crossfade modes. If CFM_CROSSFADE is selected, normal 65/* Crossfade modes. If CFM_CROSSFADE is selected, normal
64 * crossfader will activate. Selecting CFM_FLUSH is a special 66 * crossfader will activate. Selecting CFM_FLUSH is a special
65 * operation that only overwrites the pcm buffer without crossfading. 67 * operation that only overwrites the pcm buffer without crossfading.
@@ -252,7 +254,14 @@ bool pcmbuf_crossfade_init(void)
252 254
253void pcmbuf_play_stop(void) 255void pcmbuf_play_stop(void)
254{ 256{
257 mutex_lock(&pcmbuf_mutex);
258
259 /** Prevent a very tiny pop from happening by muting audio
260 * until dma has been initialized. */
261 pcm_mute(true);
255 pcm_play_stop(); 262 pcm_play_stop();
263 pcm_mute(false);
264
256 last_chunksize = 0; 265 last_chunksize = 0;
257 pcmbuf_unplayed_bytes = 0; 266 pcmbuf_unplayed_bytes = 0;
258 pcmbuf_mix_used_bytes = 0; 267 pcmbuf_mix_used_bytes = 0;
@@ -266,11 +275,13 @@ void pcmbuf_play_stop(void)
266 275
267 pcmbuf_set_boost_mode(false); 276 pcmbuf_set_boost_mode(false);
268 pcmbuf_boost(false); 277 pcmbuf_boost(false);
269 278
279 mutex_unlock(&pcmbuf_mutex);
270} 280}
271 281
272void pcmbuf_init(long bufsize) 282void pcmbuf_init(long bufsize)
273{ 283{
284 mutex_init(&pcmbuf_mutex);
274 pcmbuf_size = bufsize; 285 pcmbuf_size = bufsize;
275 audiobuffer = (char *)&audiobuf[(audiobufend - audiobuf) - 286 audiobuffer = (char *)&audiobuf[(audiobufend - audiobuf) -
276 pcmbuf_size - PCMBUF_GUARD]; 287 pcmbuf_size - PCMBUF_GUARD];
@@ -304,7 +315,16 @@ void pcmbuf_flush_audio(void)
304void pcmbuf_play_start(void) 315void pcmbuf_play_start(void)
305{ 316{
306 if (!pcm_is_playing() && pcmbuf_unplayed_bytes) 317 if (!pcm_is_playing() && pcmbuf_unplayed_bytes)
318 {
319 /** Prevent a very tiny pop from happening by muting audio
320 * until dma has been initialized. */
321 pcm_mute(true);
322
307 pcm_play_data(pcmbuf_callback); 323 pcm_play_data(pcmbuf_callback);
324
325 /* Now unmute the audio. */
326 pcm_mute(false);
327 }
308} 328}
309 329
310/** 330/**
@@ -314,6 +334,8 @@ void pcmbuf_flush_fillpos(void)
314{ 334{
315 int copy_n; 335 int copy_n;
316 336
337 mutex_lock(&pcmbuf_mutex);
338
317 copy_n = MIN(audiobuffer_fillpos, CHUNK_SIZE); 339 copy_n = MIN(audiobuffer_fillpos, CHUNK_SIZE);
318 340
319 if (copy_n) { 341 if (copy_n) {
@@ -324,7 +346,8 @@ void pcmbuf_flush_fillpos(void)
324 /* This is a fatal error situation that should never happen. */ 346 /* This is a fatal error situation that should never happen. */
325 if (!pcm_is_playing()) { 347 if (!pcm_is_playing()) {
326 logf("pcm_flush_fillpos error"); 348 logf("pcm_flush_fillpos error");
327 pcm_play_data(pcmbuf_callback); 349 pcmbuf_play_start();
350 mutex_unlock(&pcmbuf_mutex);
328 return ; 351 return ;
329 } 352 }
330 } 353 }
@@ -336,6 +359,8 @@ void pcmbuf_flush_fillpos(void)
336 audiobuffer_free -= copy_n; 359 audiobuffer_free -= copy_n;
337 audiobuffer_fillpos -= copy_n; 360 audiobuffer_fillpos -= copy_n;
338 } 361 }
362
363 mutex_unlock(&pcmbuf_mutex);
339} 364}
340 365
341/** 366/**
@@ -576,7 +601,7 @@ static bool prepare_insert(long length)
576 crossfade_active = false; 601 crossfade_active = false;
577 if (audiobuffer_free < pcmbuf_size - CHUNK_SIZE*4) { 602 if (audiobuffer_free < pcmbuf_size - CHUNK_SIZE*4) {
578 logf("pcm starting"); 603 logf("pcm starting");
579 pcm_play_data(pcmbuf_callback); 604 pcmbuf_play_start();
580 } 605 }
581 } 606 }
582 607
diff --git a/apps/playback.c b/apps/playback.c
index 77a199bd81..779fd97bde 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -294,8 +294,6 @@ bool codec_pcmbuf_insert_split_callback(void *ch1, void *ch2,
294 294
295 while (paused) 295 while (paused)
296 { 296 {
297 if (pcm_is_playing())
298 pcm_play_pause(false);
299 sleep(1); 297 sleep(1);
300 if (ci.stop_codec || ci.reload_codec || ci.seek_time) 298 if (ci.stop_codec || ci.reload_codec || ci.seek_time)
301 return true; 299 return true;
@@ -1845,15 +1843,15 @@ void audio_thread(void)
1845 1843
1846 case AUDIO_PAUSE: 1844 case AUDIO_PAUSE:
1847 logf("audio_pause"); 1845 logf("audio_pause");
1848 /* We will pause the pcm playback in audiobuffer insert function 1846 pcm_mute(true);
1849 to prevent a loop inside the pcm buffer. */ 1847 pcm_play_pause(false);
1850 // pcm_play_pause(false);
1851 paused = true; 1848 paused = true;
1852 break ; 1849 break ;
1853 1850
1854 case AUDIO_RESUME: 1851 case AUDIO_RESUME:
1855 logf("audio_resume"); 1852 logf("audio_resume");
1856 pcm_play_pause(true); 1853 pcm_play_pause(true);
1854 pcm_mute(false);
1857 paused = false; 1855 paused = false;
1858 break ; 1856 break ;
1859 1857
diff --git a/firmware/export/pcm_playback.h b/firmware/export/pcm_playback.h
index 3972e45768..5b61beb34d 100644
--- a/firmware/export/pcm_playback.h
+++ b/firmware/export/pcm_playback.h
@@ -29,6 +29,7 @@ void pcm_calculate_peaks(int *left, int *right);
29long pcm_get_bytes_waiting(void); 29long pcm_get_bytes_waiting(void);
30 30
31void pcm_play_stop(void); 31void pcm_play_stop(void);
32void pcm_mute(bool mute);
32void pcm_play_pause(bool play); 33void pcm_play_pause(bool play);
33bool pcm_is_paused(void); 34bool pcm_is_paused(void);
34bool pcm_is_playing(void); 35bool pcm_is_playing(void);
diff --git a/firmware/pcm_playback.c b/firmware/pcm_playback.c
index 6a190e4d23..ccac7843ad 100644
--- a/firmware/pcm_playback.c
+++ b/firmware/pcm_playback.c
@@ -75,11 +75,6 @@ static void dma_start(const void *addr, long size)
75 EBU1CONFIG = IIS_RESET | EBU_DEFPARM; 75 EBU1CONFIG = IIS_RESET | EBU_DEFPARM;
76#endif 76#endif
77 77
78 /** Prevent a very tiny pop from happening by muting audio
79 * until dma has been initialized. */
80 uda1380_mute(true);
81 sleep(HZ/16);
82
83 /* Set up DMA transfer */ 78 /* Set up DMA transfer */
84 SAR0 = ((unsigned long)addr); /* Source address */ 79 SAR0 = ((unsigned long)addr); /* Source address */
85 DAR0 = (unsigned long)&PDOR3; /* Destination address */ 80 DAR0 = (unsigned long)&PDOR3; /* Destination address */
@@ -92,9 +87,6 @@ static void dma_start(const void *addr, long size)
92 EBU1CONFIG = EBU_DEFPARM; 87 EBU1CONFIG = EBU_DEFPARM;
93#endif 88#endif
94 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_SINC | DMA_START; 89 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_SINC | DMA_START;
95
96 /* Now unmute the audio. */
97 uda1380_mute(false);
98} 90}
99 91
100/* Stops the DMA transfer and interrupt */ 92/* Stops the DMA transfer and interrupt */
@@ -220,14 +212,17 @@ long pcm_get_bytes_waiting(void)
220 return next_size + (BCR0 & 0xffffff); 212 return next_size + (BCR0 & 0xffffff);
221} 213}
222 214
215void pcm_mute(bool mute)
216{
217 uda1380_mute(mute);
218 if (mute)
219 sleep(HZ/16);
220}
221
223void pcm_play_stop(void) 222void pcm_play_stop(void)
224{ 223{
225 if (pcm_playing) { 224 if (pcm_playing) {
226 /* Same muting trick here to prevent a tiny pop. */
227 uda1380_mute(true);
228 sleep(HZ/16);
229 dma_stop(); 225 dma_stop();
230 uda1380_mute(false);
231 } 226 }
232} 227}
233 228
@@ -465,6 +460,11 @@ void pcm_play_stop(void)
465 } 460 }
466} 461}
467 462
463void pcm_mute(bool mute)
464{
465 (void)mute;
466}
467
468void pcm_play_pause(bool play) 468void pcm_play_pause(bool play)
469{ 469{
470 if(pcm_paused && play && next_size) 470 if(pcm_paused && play && next_size)