diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2006-01-22 10:25:07 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2006-01-22 10:25:07 +0000 |
commit | 6d6ca6b6a5641a0ab3657e60a1770a440cc52493 (patch) | |
tree | ad769586634236732aff30337e6b6465f1dad0c0 /apps | |
parent | 998610ca0bb8d12376936308631a8bed2f5e1281 (diff) | |
download | rockbox-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
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codecs/mpa.c | 35 | ||||
-rw-r--r-- | apps/pcmbuf.c | 31 | ||||
-rw-r--r-- | apps/playback.c | 8 |
3 files changed, 49 insertions, 25 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 | ||
75 | void 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 */ |
76 | enum codec_status codec_start(struct codec_api *api) | 92 | enum 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; | |||
60 | static int crossfade_pos; | 60 | static int crossfade_pos; |
61 | static int crossfade_rem; | 61 | static int crossfade_rem; |
62 | 62 | ||
63 | static 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 | ||
253 | void pcmbuf_play_stop(void) | 255 | void 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 | ||
272 | void pcmbuf_init(long bufsize) | 282 | void 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) | |||
304 | void pcmbuf_play_start(void) | 315 | void 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 | ||