summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2006-01-20 22:02:44 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2006-01-20 22:02:44 +0000
commit0e159f13cf4562cf17d0a2edd16bfd3b665c8473 (patch)
treedbb75cedac68b5124ab353e654b7f8f95f209348 /apps
parent57b1ccba2bd2b49a1fe6248878f5afec6676fe70 (diff)
downloadrockbox-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.c25
-rw-r--r--apps/pcmbuf.c3
-rw-r--r--apps/playback.c100
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 */
120next_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
230bool pcmbuf_crossfade_init(void) 230bool 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
659bool codec_seek_buffer_callback(off_t newpos) 659bool 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
1291static 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
1291static void audio_stop_playback(bool resume) 1300static 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
1493enum { 1509enum {
@@ -1497,7 +1513,7 @@ enum {
1497}; 1513};
1498 1514
1499/* Should handle all situations. */ 1515/* Should handle all situations. */
1500static int skip_next_track(void) 1516static 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
1555static int skip_previous_track(void) 1577static 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
1614bool codec_request_next_track_callback(void) 1641bool 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)
2091void audio_play(int offset) 2117void 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