diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2006-01-20 22:02:44 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2006-01-20 22:02:44 +0000 |
commit | 0e159f13cf4562cf17d0a2edd16bfd3b665c8473 (patch) | |
tree | dbb75cedac68b5124ab353e654b7f8f95f209348 /apps | |
parent | 57b1ccba2bd2b49a1fe6248878f5afec6676fe70 (diff) | |
download | rockbox-0e159f13cf4562cf17d0a2edd16bfd3b665c8473.tar.gz rockbox-0e159f13cf4562cf17d0a2edd16bfd3b665c8473.zip |
Fixed a few iriver playback quirks and issues with previous fixes.
Also fixed "TST.." bug when seeking and possible an enhancement to mp3
gapless playback also.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8402 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r-- | apps/codecs/mpa.c | 25 | ||||
-rw-r--r-- | apps/pcmbuf.c | 3 | ||||
-rw-r--r-- | apps/playback.c | 100 |
3 files changed, 88 insertions, 40 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c index 3ee2b352f1..2c946f3f0d 100644 --- a/apps/codecs/mpa.c +++ b/apps/codecs/mpa.c | |||
@@ -101,6 +101,12 @@ enum codec_status codec_start(struct codec_api *api) | |||
101 | ci->configure(DSP_SET_CLIP_MAX, (int *)(MAD_F_ONE - 1)); | 101 | ci->configure(DSP_SET_CLIP_MAX, (int *)(MAD_F_ONE - 1)); |
102 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); | 102 | ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*16)); |
103 | 103 | ||
104 | /** This label might need to be moved above all the init code, but I don't | ||
105 | * think reiniting the codec is necessary for MPEG. It might even be unwanted | ||
106 | * for gapless playback. | ||
107 | * Reinitializing seems to be necessary to avoid playback quircks when seeking. */ | ||
108 | next_track: | ||
109 | |||
104 | ci->memset(&stream, 0, sizeof(struct mad_stream)); | 110 | ci->memset(&stream, 0, sizeof(struct mad_stream)); |
105 | ci->memset(&frame, 0, sizeof(struct mad_frame)); | 111 | ci->memset(&frame, 0, sizeof(struct mad_frame)); |
106 | ci->memset(&synth, 0, sizeof(struct mad_synth)); | 112 | ci->memset(&synth, 0, sizeof(struct mad_synth)); |
@@ -114,10 +120,6 @@ enum codec_status codec_start(struct codec_api *api) | |||
114 | frame.overlap = &mad_frame_overlap; | 120 | frame.overlap = &mad_frame_overlap; |
115 | stream.main_data = &mad_main_data; | 121 | stream.main_data = &mad_main_data; |
116 | 122 | ||
117 | /* This label might need to be moved above all the init code, but I don't | ||
118 | think reiniting the codec is necessary for MPEG. It might even be unwanted | ||
119 | for gapless playback */ | ||
120 | next_track: | ||
121 | file_end = 0; | 123 | file_end = 0; |
122 | while (!*ci->taginfo_ready && !ci->stop_codec) | 124 | while (!*ci->taginfo_ready && !ci->stop_codec) |
123 | ci->sleep(1); | 125 | ci->sleep(1); |
@@ -156,14 +158,21 @@ next_track: | |||
156 | 158 | ||
157 | samplesdone = ((int64_t) (ci->seek_time - 1)) | 159 | samplesdone = ((int64_t) (ci->seek_time - 1)) |
158 | * current_frequency / 1000; | 160 | * current_frequency / 1000; |
159 | newpos = ci->mp3_get_filepos(ci->seek_time-1) + | 161 | |
160 | ci->id3->first_frame_offset; | 162 | if (ci->seek_time-1 == 0) |
163 | newpos = 0; | ||
164 | else | ||
165 | newpos = ci->mp3_get_filepos(ci->seek_time-1) + | ||
166 | ci->id3->first_frame_offset; | ||
161 | 167 | ||
162 | if (!ci->seek_buffer(newpos)) | 168 | if (!ci->seek_buffer(newpos)) |
163 | goto next_track; | 169 | goto next_track; |
164 | if (newpos == 0) | ||
165 | samples_to_skip = start_skip; | ||
166 | ci->seek_complete(); | 170 | ci->seek_complete(); |
171 | if (newpos == 0) | ||
172 | { | ||
173 | ci->id3->elapsed = 0; | ||
174 | goto next_track; | ||
175 | } | ||
167 | } | 176 | } |
168 | 177 | ||
169 | /* Lock buffers */ | 178 | /* Lock buffers */ |
diff --git a/apps/pcmbuf.c b/apps/pcmbuf.c index f1988fd3f4..66dd47eb3d 100644 --- a/apps/pcmbuf.c +++ b/apps/pcmbuf.c | |||
@@ -229,7 +229,8 @@ bool pcmbuf_is_lowdata(void) | |||
229 | 229 | ||
230 | bool pcmbuf_crossfade_init(void) | 230 | bool pcmbuf_crossfade_init(void) |
231 | { | 231 | { |
232 | if (pcmbuf_size - audiobuffer_free < CHUNK_SIZE * 8 || !crossfade_enabled | 232 | if (pcmbuf_size - audiobuffer_free < CHUNK_SIZE * 8 |
233 | || !pcmbuf_is_crossfade_enabled() | ||
233 | || crossfade_active || crossfade_init) { | 234 | || crossfade_active || crossfade_init) { |
234 | pcmbuf_flush_audio(); | 235 | pcmbuf_flush_audio(); |
235 | return false; | 236 | return false; |
diff --git a/apps/playback.c b/apps/playback.c index ff2f9d58cc..3da4b6fbdb 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -653,7 +653,7 @@ void codec_seek_complete_callback(void) | |||
653 | { | 653 | { |
654 | /* assume we're called from non-voice codec, as they shouldn't seek */ | 654 | /* assume we're called from non-voice codec, as they shouldn't seek */ |
655 | ci.seek_time = 0; | 655 | ci.seek_time = 0; |
656 | pcmbuf_flush_audio(); | 656 | pcmbuf_play_stop(); |
657 | } | 657 | } |
658 | 658 | ||
659 | bool codec_seek_buffer_callback(off_t newpos) | 659 | bool codec_seek_buffer_callback(off_t newpos) |
@@ -1288,6 +1288,15 @@ static void audio_clear_track_entries(bool buffered_only) | |||
1288 | } | 1288 | } |
1289 | } | 1289 | } |
1290 | 1290 | ||
1291 | static void stop_codec_flush(void) | ||
1292 | { | ||
1293 | ci.stop_codec = true; | ||
1294 | pcmbuf_play_stop(); | ||
1295 | while (audio_codec_loaded) | ||
1296 | yield(); | ||
1297 | pcmbuf_play_stop(); | ||
1298 | } | ||
1299 | |||
1291 | static void audio_stop_playback(bool resume) | 1300 | static void audio_stop_playback(bool resume) |
1292 | { | 1301 | { |
1293 | logf("stop_playback:%d", resume); | 1302 | logf("stop_playback:%d", resume); |
@@ -1296,14 +1305,11 @@ static void audio_stop_playback(bool resume) | |||
1296 | playlist_update_resume_info(resume ? audio_current_track() : NULL); | 1305 | playlist_update_resume_info(resume ? audio_current_track() : NULL); |
1297 | playing = false; | 1306 | playing = false; |
1298 | filling = false; | 1307 | filling = false; |
1299 | ci.stop_codec = true; | 1308 | stop_codec_flush(); |
1300 | if (current_fd >= 0) { | 1309 | if (current_fd >= 0) { |
1301 | close(current_fd); | 1310 | close(current_fd); |
1302 | current_fd = -1; | 1311 | current_fd = -1; |
1303 | } | 1312 | } |
1304 | pcmbuf_play_stop(); | ||
1305 | while (audio_codec_loaded) | ||
1306 | yield(); | ||
1307 | 1313 | ||
1308 | track_count = 0; | 1314 | track_count = 0; |
1309 | /* Mark all entries null. */ | 1315 | /* Mark all entries null. */ |
@@ -1478,16 +1484,26 @@ static void audio_update_trackinfo(void) | |||
1478 | ci.curpos = 0; | 1484 | ci.curpos = 0; |
1479 | cur_ti->start_pos = 0; | 1485 | cur_ti->start_pos = 0; |
1480 | ci.taginfo_ready = (bool *)&cur_ti->taginfo_ready; | 1486 | ci.taginfo_ready = (bool *)&cur_ti->taginfo_ready; |
1481 | if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()) { | 1487 | |
1488 | /* Manual track change (always crossfade or flush audio). */ | ||
1489 | if (new_track) | ||
1490 | { | ||
1482 | pcmbuf_crossfade_init(); | 1491 | pcmbuf_crossfade_init(); |
1483 | codec_track_changed(); | 1492 | codec_track_changed(); |
1484 | } else { | ||
1485 | pcmbuf_add_event(codec_track_changed); | ||
1486 | } | 1493 | } |
1487 | 1494 | ||
1488 | /* Manual track change. */ | 1495 | /* Automatic track change with crossfade. */ |
1489 | if (new_track) | 1496 | else if (pcmbuf_is_crossfade_enabled() && !pcmbuf_is_crossfade_active()) |
1497 | { | ||
1498 | pcmbuf_crossfade_init(); | ||
1490 | codec_track_changed(); | 1499 | codec_track_changed(); |
1500 | } | ||
1501 | |||
1502 | /* Gapless playback. */ | ||
1503 | else | ||
1504 | { | ||
1505 | pcmbuf_add_event(codec_track_changed); | ||
1506 | } | ||
1491 | } | 1507 | } |
1492 | 1508 | ||
1493 | enum { | 1509 | enum { |
@@ -1497,7 +1513,7 @@ enum { | |||
1497 | }; | 1513 | }; |
1498 | 1514 | ||
1499 | /* Should handle all situations. */ | 1515 | /* Should handle all situations. */ |
1500 | static int skip_next_track(void) | 1516 | static int skip_next_track(bool inside_codec_thread) |
1501 | { | 1517 | { |
1502 | logf("skip next"); | 1518 | logf("skip next"); |
1503 | /* Manual track skipping. */ | 1519 | /* Manual track skipping. */ |
@@ -1529,10 +1545,16 @@ static int skip_next_track(void) | |||
1529 | ci.reload_codec = true; | 1545 | ci.reload_codec = true; |
1530 | /* Stop playback if manual track change. */ | 1546 | /* Stop playback if manual track change. */ |
1531 | if (new_track != 0 && !pcmbuf_is_crossfade_enabled()) | 1547 | if (new_track != 0 && !pcmbuf_is_crossfade_enabled()) |
1532 | pcmbuf_play_stop(); | 1548 | { |
1549 | if (inside_codec_thread) | ||
1550 | pcmbuf_play_stop(); | ||
1551 | else | ||
1552 | stop_codec_flush(); | ||
1553 | } | ||
1554 | else if (pcmbuf_is_crossfade_enabled()) | ||
1555 | pcmbuf_crossfade_init(); | ||
1533 | 1556 | ||
1534 | /* Don't flush buffer */ | 1557 | queue_post(&audio_queue, AUDIO_PLAY, 0); |
1535 | queue_post(&audio_queue, AUDIO_PLAY, (bool *)false); | ||
1536 | return SKIP_OK_DISK; | 1558 | return SKIP_OK_DISK; |
1537 | } | 1559 | } |
1538 | 1560 | ||
@@ -1552,7 +1574,7 @@ static int skip_next_track(void) | |||
1552 | return SKIP_OK_RAM; | 1574 | return SKIP_OK_RAM; |
1553 | } | 1575 | } |
1554 | 1576 | ||
1555 | static int skip_previous_track(void) | 1577 | static int skip_previous_track(bool inside_codec_thread) |
1556 | { | 1578 | { |
1557 | logf("skip previous"); | 1579 | logf("skip previous"); |
1558 | last_peek_offset++; | 1580 | last_peek_offset++; |
@@ -1566,10 +1588,14 @@ static int skip_previous_track(void) | |||
1566 | ci.reload_codec = true; | 1588 | ci.reload_codec = true; |
1567 | /* Stop playback. */ | 1589 | /* Stop playback. */ |
1568 | /* FIXME: Only stop playback if disk is not spinning! */ | 1590 | /* FIXME: Only stop playback if disk is not spinning! */ |
1569 | if (!pcmbuf_is_crossfade_enabled()) | 1591 | if (pcmbuf_is_crossfade_enabled()) |
1592 | pcmbuf_crossfade_init(); | ||
1593 | else if (inside_codec_thread) | ||
1570 | pcmbuf_play_stop(); | 1594 | pcmbuf_play_stop(); |
1595 | else | ||
1596 | stop_codec_flush(); | ||
1571 | 1597 | ||
1572 | queue_post(&audio_queue, AUDIO_PLAY, (bool *)true); | 1598 | queue_post(&audio_queue, AUDIO_PLAY, 0); |
1573 | return SKIP_OK_DISK; | 1599 | return SKIP_OK_DISK; |
1574 | } | 1600 | } |
1575 | 1601 | ||
@@ -1583,6 +1609,7 @@ static int skip_previous_track(void) | |||
1583 | cur_ti->available = cur_ti->filesize; | 1609 | cur_ti->available = cur_ti->filesize; |
1584 | if (buf_ridx < 0) | 1610 | if (buf_ridx < 0) |
1585 | buf_ridx += filebuflen; | 1611 | buf_ridx += filebuflen; |
1612 | |||
1586 | audio_update_trackinfo(); | 1613 | audio_update_trackinfo(); |
1587 | 1614 | ||
1588 | return SKIP_OK_RAM; | 1615 | return SKIP_OK_RAM; |
@@ -1595,7 +1622,7 @@ static void audio_change_track(void) | |||
1595 | 1622 | ||
1596 | if (!ci.reload_codec) | 1623 | if (!ci.reload_codec) |
1597 | { | 1624 | { |
1598 | if (skip_next_track() == SKIP_FAIL) | 1625 | if (skip_next_track(false) == SKIP_FAIL) |
1599 | { | 1626 | { |
1600 | logf("No more tracks"); | 1627 | logf("No more tracks"); |
1601 | while (pcm_is_playing()) | 1628 | while (pcm_is_playing()) |
@@ -1607,8 +1634,8 @@ static void audio_change_track(void) | |||
1607 | 1634 | ||
1608 | ci.reload_codec = false; | 1635 | ci.reload_codec = false; |
1609 | /* Needed for fast skipping. */ | 1636 | /* Needed for fast skipping. */ |
1610 | //if (cur_ti->codecsize > 0) | 1637 | if (cur_ti->codecsize > 0) |
1611 | // queue_post(&codec_queue, CODEC_LOAD, 0); | 1638 | queue_post(&codec_queue, CODEC_LOAD, 0); |
1612 | } | 1639 | } |
1613 | 1640 | ||
1614 | bool codec_request_next_track_callback(void) | 1641 | bool codec_request_next_track_callback(void) |
@@ -1629,13 +1656,13 @@ bool codec_request_next_track_callback(void) | |||
1629 | 1656 | ||
1630 | /* Advance to next track. */ | 1657 | /* Advance to next track. */ |
1631 | if (new_track >= 0 || !ci.reload_codec) { | 1658 | if (new_track >= 0 || !ci.reload_codec) { |
1632 | if (skip_next_track() != SKIP_OK_RAM) | 1659 | if (skip_next_track(true) != SKIP_OK_RAM) |
1633 | return false; | 1660 | return false; |
1634 | } | 1661 | } |
1635 | 1662 | ||
1636 | /* Advance to previous track. */ | 1663 | /* Advance to previous track. */ |
1637 | else { | 1664 | else { |
1638 | if (skip_previous_track() != SKIP_OK_RAM) | 1665 | if (skip_previous_track(true) != SKIP_OK_RAM) |
1639 | return false; | 1666 | return false; |
1640 | } | 1667 | } |
1641 | 1668 | ||
@@ -1654,7 +1681,7 @@ bool codec_request_next_track_callback(void) | |||
1654 | if (cur_ti->codecsize == 0) | 1681 | if (cur_ti->codecsize == 0) |
1655 | { | 1682 | { |
1656 | logf("Loading from disk [2]..."); | 1683 | logf("Loading from disk [2]..."); |
1657 | queue_post(&audio_queue, AUDIO_PLAY, (bool *)(new_track != 0)); | 1684 | queue_post(&audio_queue, AUDIO_PLAY, 0); |
1658 | } | 1685 | } |
1659 | else | 1686 | else |
1660 | ci.reload_codec = true; | 1687 | ci.reload_codec = true; |
@@ -1692,12 +1719,15 @@ static void initiate_track_change(int peek_index) | |||
1692 | { | 1719 | { |
1693 | /* Detect if disk is spinning or already loading. */ | 1720 | /* Detect if disk is spinning or already loading. */ |
1694 | if (filling || ci.reload_codec || !audio_codec_loaded) { | 1721 | if (filling || ci.reload_codec || !audio_codec_loaded) { |
1695 | queue_post(&audio_queue, AUDIO_PLAY, (bool *)true); | 1722 | if (pcmbuf_is_crossfade_enabled()) |
1723 | pcmbuf_crossfade_init(); | ||
1724 | else | ||
1725 | pcmbuf_play_stop(); | ||
1726 | ci.stop_codec = true; | ||
1727 | queue_post(&audio_queue, AUDIO_PLAY, 0); | ||
1696 | } else { | 1728 | } else { |
1697 | new_track = peek_index; | 1729 | new_track = peek_index; |
1698 | ci.reload_codec = true; | 1730 | ci.reload_codec = true; |
1699 | if (!pcmbuf_is_crossfade_enabled()) | ||
1700 | pcmbuf_flush_audio(); | ||
1701 | } | 1731 | } |
1702 | 1732 | ||
1703 | codec_track_changed(); | 1733 | codec_track_changed(); |
@@ -1771,14 +1801,10 @@ void audio_thread(void) | |||
1771 | ci.reload_codec = false; | 1801 | ci.reload_codec = false; |
1772 | ci.seek_time = 0; | 1802 | ci.seek_time = 0; |
1773 | 1803 | ||
1774 | /* Only flush audio if it has been requested. */ | ||
1775 | if ((bool)ev.data) | ||
1776 | pcmbuf_crossfade_init(); | ||
1777 | |||
1778 | while (audio_codec_loaded) | 1804 | while (audio_codec_loaded) |
1779 | yield(); | 1805 | yield(); |
1806 | |||
1780 | audio_play_start((int)ev.data); | 1807 | audio_play_start((int)ev.data); |
1781 | |||
1782 | playlist_update_resume_info(audio_current_track()); | 1808 | playlist_update_resume_info(audio_current_track()); |
1783 | 1809 | ||
1784 | /* If there are no tracks in the playlist, then the playlist | 1810 | /* If there are no tracks in the playlist, then the playlist |
@@ -2091,6 +2117,18 @@ bool audio_has_changed_track(void) | |||
2091 | void audio_play(int offset) | 2117 | void audio_play(int offset) |
2092 | { | 2118 | { |
2093 | logf("audio_play"); | 2119 | logf("audio_play"); |
2120 | if (pcmbuf_is_crossfade_enabled()) | ||
2121 | { | ||
2122 | ci.stop_codec = true; | ||
2123 | sleep(1); | ||
2124 | pcmbuf_crossfade_init(); | ||
2125 | } | ||
2126 | else | ||
2127 | { | ||
2128 | stop_codec_flush(); | ||
2129 | pcmbuf_play_stop(); | ||
2130 | } | ||
2131 | |||
2094 | queue_post(&audio_queue, AUDIO_PLAY, (void *)offset); | 2132 | queue_post(&audio_queue, AUDIO_PLAY, (void *)offset); |
2095 | } | 2133 | } |
2096 | 2134 | ||