diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/mpeg.c | 143 |
1 files changed, 75 insertions, 68 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c index a7d5480706..64b1165c23 100644 --- a/firmware/mpeg.c +++ b/firmware/mpeg.c | |||
@@ -95,17 +95,17 @@ extern int playlist_amount(void); | |||
95 | extern void update_file_pos( int id, int pos ); | 95 | extern void update_file_pos( int id, int pos ); |
96 | 96 | ||
97 | /* list of tracks in memory */ | 97 | /* list of tracks in memory */ |
98 | #define MAX_ID3_TAGS (1<<4) /* Must be power of 2 */ | 98 | #define MAX_TRACK_ENTRIES (1<<4) /* Must be power of 2 */ |
99 | #define MAX_ID3_TAGS_MASK (MAX_ID3_TAGS - 1) | 99 | #define MAX_TRACK_ENTRIES_MASK (MAX_TRACK_ENTRIES - 1) |
100 | 100 | ||
101 | struct id3tag | 101 | struct trackdata |
102 | { | 102 | { |
103 | struct mp3entry id3; | 103 | struct mp3entry id3; |
104 | int mempos; | 104 | int mempos; |
105 | int load_ahead_index; | 105 | int load_ahead_index; |
106 | }; | 106 | }; |
107 | 107 | ||
108 | static struct id3tag id3tags[MAX_ID3_TAGS]; | 108 | static struct trackdata trackdata[MAX_TRACK_ENTRIES]; |
109 | 109 | ||
110 | static bool v1first = false; | 110 | static bool v1first = false; |
111 | 111 | ||
@@ -114,12 +114,12 @@ static unsigned int last_track_counter = 0; | |||
114 | 114 | ||
115 | #ifndef SIMULATOR | 115 | #ifndef SIMULATOR |
116 | 116 | ||
117 | static int tag_read_idx = 0; | 117 | static int track_read_idx = 0; |
118 | static int tag_write_idx = 0; | 118 | static int track_write_idx = 0; |
119 | 119 | ||
120 | static int num_tracks_in_memory(void) | 120 | static int num_tracks_in_memory(void) |
121 | { | 121 | { |
122 | return (tag_write_idx - tag_read_idx) & MAX_ID3_TAGS_MASK; | 122 | return (track_write_idx - track_read_idx) & MAX_TRACK_ENTRIES_MASK; |
123 | } | 123 | } |
124 | #endif /* #ifndef SIMULATOR */ | 124 | #endif /* #ifndef SIMULATOR */ |
125 | 125 | ||
@@ -129,11 +129,11 @@ static void debug_tags(void) | |||
129 | #ifdef DEBUG_TAGS | 129 | #ifdef DEBUG_TAGS |
130 | int i; | 130 | int i; |
131 | 131 | ||
132 | for(i = 0;i < MAX_ID3_TAGS;i++) | 132 | for(i = 0;i < MAX_TRACK_ENTRIES;i++) |
133 | { | 133 | { |
134 | DEBUGF("%d - %s\n", i, id3tags[i].id3.path); | 134 | DEBUGF("%d - %s\n", i, trackdata[i].id3.path); |
135 | } | 135 | } |
136 | DEBUGF("read: %d, write :%d\n", tag_read_idx, tag_write_idx); | 136 | DEBUGF("read: %d, write :%d\n", track_read_idx, track_write_idx); |
137 | DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory()); | 137 | DEBUGF("num_tracks_in_memory: %d\n", num_tracks_in_memory()); |
138 | #endif /* #ifdef DEBUG_TAGS */ | 138 | #endif /* #ifdef DEBUG_TAGS */ |
139 | } | 139 | } |
@@ -143,7 +143,7 @@ static void remove_current_tag(void) | |||
143 | if(num_tracks_in_memory() > 0) | 143 | if(num_tracks_in_memory() > 0) |
144 | { | 144 | { |
145 | /* First move the index, so nobody tries to access the tag */ | 145 | /* First move the index, so nobody tries to access the tag */ |
146 | tag_read_idx = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; | 146 | track_read_idx = (track_read_idx+1) & MAX_TRACK_ENTRIES_MASK; |
147 | debug_tags(); | 147 | debug_tags(); |
148 | } | 148 | } |
149 | else | 149 | else |
@@ -154,16 +154,24 @@ static void remove_current_tag(void) | |||
154 | 154 | ||
155 | static void remove_all_non_current_tags(void) | 155 | static void remove_all_non_current_tags(void) |
156 | { | 156 | { |
157 | tag_write_idx = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; | 157 | track_write_idx = (track_read_idx+1) & MAX_TRACK_ENTRIES_MASK; |
158 | debug_tags(); | 158 | debug_tags(); |
159 | } | 159 | } |
160 | 160 | ||
161 | static void remove_all_tags(void) | 161 | static void remove_all_tags(void) |
162 | { | 162 | { |
163 | tag_write_idx = tag_read_idx; | 163 | track_write_idx = track_read_idx; |
164 | 164 | ||
165 | debug_tags(); | 165 | debug_tags(); |
166 | } | 166 | } |
167 | |||
168 | static struct trackdata *get_trackdata(int offset) | ||
169 | { | ||
170 | if(offset > num_tracks_in_memory()) | ||
171 | return NULL; | ||
172 | else | ||
173 | return &trackdata[(track_read_idx + offset) & MAX_TRACK_ENTRIES_MASK]; | ||
174 | } | ||
167 | #endif /* #ifndef SIMULATOR */ | 175 | #endif /* #ifndef SIMULATOR */ |
168 | 176 | ||
169 | static void set_elapsed(struct mp3entry* id3) | 177 | static void set_elapsed(struct mp3entry* id3) |
@@ -477,9 +485,7 @@ static int get_unplayed_space_current_song(void) | |||
477 | 485 | ||
478 | if (num_tracks_in_memory() > 1) | 486 | if (num_tracks_in_memory() > 1) |
479 | { | 487 | { |
480 | int track_offset = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; | 488 | space = get_trackdata(1)->mempos - audiobuf_read; |
481 | |||
482 | space = id3tags[track_offset].mempos - audiobuf_read; | ||
483 | } | 489 | } |
484 | else | 490 | else |
485 | { | 491 | { |
@@ -666,7 +672,7 @@ void rec_tick(void) | |||
666 | 672 | ||
667 | void playback_tick(void) | 673 | void playback_tick(void) |
668 | { | 674 | { |
669 | id3tags[tag_read_idx].id3.elapsed += | 675 | get_trackdata(0)->id3.elapsed += |
670 | (current_tick - last_dma_tick) * 1000 / HZ; | 676 | (current_tick - last_dma_tick) * 1000 / HZ; |
671 | last_dma_tick = current_tick; | 677 | last_dma_tick = current_tick; |
672 | } | 678 | } |
@@ -686,7 +692,8 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
686 | { | 692 | { |
687 | int unplayed_space_left; | 693 | int unplayed_space_left; |
688 | int space_until_end_of_buffer; | 694 | int space_until_end_of_buffer; |
689 | int track_offset = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; | 695 | int track_offset = 1; |
696 | struct trackdata *track; | ||
690 | 697 | ||
691 | audiobuf_read += last_dma_chunk_size; | 698 | audiobuf_read += last_dma_chunk_size; |
692 | if(audiobuf_read >= audiobuflen) | 699 | if(audiobuf_read >= audiobuflen) |
@@ -695,10 +702,10 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
695 | /* First, check if we are on a track boundary */ | 702 | /* First, check if we are on a track boundary */ |
696 | if (num_tracks_in_memory() > 1) | 703 | if (num_tracks_in_memory() > 1) |
697 | { | 704 | { |
698 | if (audiobuf_read == id3tags[track_offset].mempos) | 705 | if (audiobuf_read == get_trackdata(track_offset)->mempos) |
699 | { | 706 | { |
700 | queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0); | 707 | queue_post(&mpeg_queue, MPEG_TRACK_CHANGE, 0); |
701 | track_offset = (track_offset+1) & MAX_ID3_TAGS_MASK; | 708 | track_offset++; |
702 | } | 709 | } |
703 | } | 710 | } |
704 | 711 | ||
@@ -721,20 +728,21 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
721 | /* several tracks loaded? */ | 728 | /* several tracks loaded? */ |
722 | if (num_tracks_in_memory() > 1) | 729 | if (num_tracks_in_memory() > 1) |
723 | { | 730 | { |
731 | track = get_trackdata(track_offset); | ||
732 | |||
724 | /* will we move across the track boundary? */ | 733 | /* will we move across the track boundary? */ |
725 | if (( audiobuf_read < id3tags[track_offset].mempos ) && | 734 | if (( audiobuf_read < track->mempos ) && |
726 | ((audiobuf_read+last_dma_chunk_size) > | 735 | ((audiobuf_read+last_dma_chunk_size) > |
727 | id3tags[track_offset].mempos )) | 736 | track->mempos )) |
728 | { | 737 | { |
729 | /* Make sure that we end exactly on the boundary */ | 738 | /* Make sure that we end exactly on the boundary */ |
730 | last_dma_chunk_size = id3tags[track_offset].mempos | 739 | last_dma_chunk_size = track->mempos - audiobuf_read; |
731 | - audiobuf_read; | ||
732 | } | 740 | } |
733 | } | 741 | } |
734 | 742 | ||
735 | *psize = last_dma_chunk_size & 0xffff; | 743 | *psize = last_dma_chunk_size & 0xffff; |
736 | *ppbuf = audiobuf + audiobuf_read; | 744 | *ppbuf = audiobuf + audiobuf_read; |
737 | id3tags[tag_read_idx].id3.offset += last_dma_chunk_size; | 745 | get_trackdata(0)->id3.offset += last_dma_chunk_size; |
738 | 746 | ||
739 | /* Update the watermark debug level */ | 747 | /* Update the watermark debug level */ |
740 | if(unplayed_space_left < lowest_watermark_level) | 748 | if(unplayed_space_left < lowest_watermark_level) |
@@ -770,27 +778,31 @@ static void transfer_end(unsigned char** ppbuf, int* psize) | |||
770 | wake_up_thread(); | 778 | wake_up_thread(); |
771 | } | 779 | } |
772 | 780 | ||
773 | static int add_track_to_tag_list(const char *filename) | 781 | static struct trackdata *add_track_to_tag_list(const char *filename) |
774 | { | 782 | { |
775 | if(num_tracks_in_memory() >= MAX_ID3_TAGS) | 783 | struct trackdata *track; |
784 | |||
785 | if(num_tracks_in_memory() >= MAX_TRACK_ENTRIES) | ||
776 | { | 786 | { |
777 | DEBUGF("Tag memory is full\n"); | 787 | DEBUGF("Tag memory is full\n"); |
778 | return -1; | 788 | return NULL; |
779 | } | 789 | } |
780 | 790 | ||
791 | track = &trackdata[track_write_idx]; | ||
792 | |||
781 | /* grab id3 tag of new file and | 793 | /* grab id3 tag of new file and |
782 | remember where in memory it starts */ | 794 | remember where in memory it starts */ |
783 | if(mp3info(&id3tags[tag_write_idx].id3, filename, v1first)) | 795 | if(mp3info(&track->id3, filename, v1first)) |
784 | { | 796 | { |
785 | DEBUGF("Bad mp3\n"); | 797 | DEBUGF("Bad mp3\n"); |
786 | return -1; | 798 | return NULL; |
787 | } | 799 | } |
788 | id3tags[tag_write_idx].mempos = audiobuf_write; | 800 | track->mempos = audiobuf_write; |
789 | id3tags[tag_write_idx].id3.elapsed = 0; | 801 | track->id3.elapsed = 0; |
790 | 802 | ||
791 | tag_write_idx = (tag_write_idx+1) & MAX_ID3_TAGS_MASK; | 803 | track_write_idx = (track_write_idx+1) & MAX_TRACK_ENTRIES_MASK; |
792 | debug_tags(); | 804 | debug_tags(); |
793 | return 0; | 805 | return track; |
794 | } | 806 | } |
795 | 807 | ||
796 | static int new_file(int steps) | 808 | static int new_file(int steps) |
@@ -798,6 +810,7 @@ static int new_file(int steps) | |||
798 | int max_steps = playlist_amount(); | 810 | int max_steps = playlist_amount(); |
799 | int start = 0; | 811 | int start = 0; |
800 | int i; | 812 | int i; |
813 | struct trackdata *track; | ||
801 | 814 | ||
802 | /* Find out how many steps to advance. The load_ahead_index field tells | 815 | /* Find out how many steps to advance. The load_ahead_index field tells |
803 | us how many playlist entries it had to skip to get to a valid one. | 816 | us how many playlist entries it had to skip to get to a valid one. |
@@ -805,11 +818,10 @@ static int new_file(int steps) | |||
805 | if(steps > 0 && num_tracks_in_memory() > 1) | 818 | if(steps > 0 && num_tracks_in_memory() > 1) |
806 | { | 819 | { |
807 | /* Begin with the song after the currently playing one */ | 820 | /* Begin with the song after the currently playing one */ |
808 | i = (tag_read_idx + 1) & MAX_ID3_TAGS_MASK; | 821 | i = 1; |
809 | while(i != tag_write_idx) | 822 | while((track = get_trackdata(i++))) |
810 | { | 823 | { |
811 | start += id3tags[i].load_ahead_index; | 824 | start += track->load_ahead_index; |
812 | i = (i+1) & MAX_ID3_TAGS_MASK; | ||
813 | } | 825 | } |
814 | } | 826 | } |
815 | 827 | ||
@@ -832,9 +844,9 @@ static int new_file(int steps) | |||
832 | } | 844 | } |
833 | else | 845 | else |
834 | { | 846 | { |
835 | int new_tag_idx = tag_write_idx; | 847 | struct trackdata *track = add_track_to_tag_list(trackname); |
836 | 848 | ||
837 | if(add_track_to_tag_list(trackname)) | 849 | if(!track) |
838 | { | 850 | { |
839 | /* Bad mp3 file */ | 851 | /* Bad mp3 file */ |
840 | if(steps < 0) | 852 | if(steps < 0) |
@@ -848,19 +860,19 @@ static int new_file(int steps) | |||
848 | { | 860 | { |
849 | /* skip past id3v2 tag */ | 861 | /* skip past id3v2 tag */ |
850 | lseek(mpeg_file, | 862 | lseek(mpeg_file, |
851 | id3tags[new_tag_idx].id3.first_frame_offset, | 863 | track->id3.first_frame_offset, |
852 | SEEK_SET); | 864 | SEEK_SET); |
853 | id3tags[new_tag_idx].id3.index = steps; | 865 | track->id3.index = steps; |
854 | id3tags[new_tag_idx].load_ahead_index = steps; | 866 | track->load_ahead_index = steps; |
855 | id3tags[new_tag_idx].id3.offset = 0; | 867 | track->id3.offset = 0; |
856 | 868 | ||
857 | if(id3tags[new_tag_idx].id3.vbr) | 869 | if(track->id3.vbr) |
858 | /* Average bitrate * 1.5 */ | 870 | /* Average bitrate * 1.5 */ |
859 | recalculate_watermark( | 871 | recalculate_watermark( |
860 | (id3tags[new_tag_idx].id3.bitrate * 3) / 2); | 872 | (track->id3.bitrate * 3) / 2); |
861 | else | 873 | else |
862 | recalculate_watermark( | 874 | recalculate_watermark( |
863 | id3tags[new_tag_idx].id3.bitrate); | 875 | track->id3.bitrate); |
864 | 876 | ||
865 | } | 877 | } |
866 | } | 878 | } |
@@ -889,11 +901,13 @@ static void stop_playing(void) | |||
889 | static void update_playlist(void) | 901 | static void update_playlist(void) |
890 | { | 902 | { |
891 | int index; | 903 | int index; |
904 | struct trackdata *track; | ||
892 | 905 | ||
893 | if (num_tracks_in_memory() > 0) | 906 | if (num_tracks_in_memory() > 0) |
894 | { | 907 | { |
895 | index = playlist_next(id3tags[tag_read_idx].id3.index); | 908 | track = get_trackdata(0); |
896 | id3tags[tag_read_idx].id3.index = index; | 909 | index = playlist_next(track->id3.index); |
910 | track->id3.index = index; | ||
897 | } | 911 | } |
898 | } | 912 | } |
899 | 913 | ||
@@ -1098,7 +1112,7 @@ static void mpeg_thread(void) | |||
1098 | 1112 | ||
1099 | /* mid-song resume? */ | 1113 | /* mid-song resume? */ |
1100 | if (start_offset) { | 1114 | if (start_offset) { |
1101 | struct mp3entry* id3 = &id3tags[tag_read_idx].id3; | 1115 | struct mp3entry* id3 = &get_trackdata(0)->id3; |
1102 | lseek(mpeg_file, start_offset, SEEK_SET); | 1116 | lseek(mpeg_file, start_offset, SEEK_SET); |
1103 | id3->offset = start_offset; | 1117 | id3->offset = start_offset; |
1104 | set_elapsed(id3); | 1118 | set_elapsed(id3); |
@@ -1106,7 +1120,7 @@ static void mpeg_thread(void) | |||
1106 | else { | 1120 | else { |
1107 | /* skip past id3v2 tag */ | 1121 | /* skip past id3v2 tag */ |
1108 | lseek(mpeg_file, | 1122 | lseek(mpeg_file, |
1109 | id3tags[tag_read_idx].id3.first_frame_offset, | 1123 | get_trackdata(0)->id3.first_frame_offset, |
1110 | SEEK_SET); | 1124 | SEEK_SET); |
1111 | 1125 | ||
1112 | } | 1126 | } |
@@ -1169,7 +1183,7 @@ static void mpeg_thread(void) | |||
1169 | mp3_play_pause(false); | 1183 | mp3_play_pause(false); |
1170 | 1184 | ||
1171 | track_change(); | 1185 | track_change(); |
1172 | audiobuf_read = id3tags[tag_read_idx].mempos; | 1186 | audiobuf_read = get_trackdata(0)->mempos; |
1173 | last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); | 1187 | last_dma_chunk_size = MIN(0x2000, get_unplayed_space_current_song()); |
1174 | mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); | 1188 | mp3_play_data(audiobuf + audiobuf_read, last_dma_chunk_size, transfer_end); |
1175 | dma_underrun = false; | 1189 | dma_underrun = false; |
@@ -1289,16 +1303,12 @@ static void mpeg_thread(void) | |||
1289 | { | 1303 | { |
1290 | /* We have started loading other tracks that need to be | 1304 | /* We have started loading other tracks that need to be |
1291 | accounted for */ | 1305 | accounted for */ |
1292 | int i = tag_read_idx; | 1306 | struct trackdata *track; |
1293 | int j = tag_write_idx - 1; | 1307 | int i = 0; |
1294 | 1308 | ||
1295 | if (j < 0) | 1309 | while((track = get_trackdata(i++))) |
1296 | j = MAX_ID3_TAGS - 1; | ||
1297 | |||
1298 | while (i != j) | ||
1299 | { | 1310 | { |
1300 | curpos += id3tags[i].id3.filesize; | 1311 | curpos += track->id3.filesize; |
1301 | i = (i+1) & MAX_ID3_TAGS_MASK; | ||
1302 | } | 1312 | } |
1303 | } | 1313 | } |
1304 | 1314 | ||
@@ -1398,11 +1408,8 @@ static void mpeg_thread(void) | |||
1398 | 1408 | ||
1399 | if (numtracks > 1) | 1409 | if (numtracks > 1) |
1400 | { | 1410 | { |
1401 | /* Reload songs */ | ||
1402 | int next = (tag_read_idx+1) & MAX_ID3_TAGS_MASK; | ||
1403 | |||
1404 | /* Reset the buffer */ | 1411 | /* Reset the buffer */ |
1405 | audiobuf_write = id3tags[next].mempos; | 1412 | audiobuf_write = get_trackdata(1)->mempos; |
1406 | 1413 | ||
1407 | /* Reset swapwrite unless we're still swapping current | 1414 | /* Reset swapwrite unless we're still swapping current |
1408 | track */ | 1415 | track */ |
@@ -2020,7 +2027,7 @@ struct mp3entry* audio_current_track() | |||
2020 | return &taginfo; | 2027 | return &taginfo; |
2021 | #else | 2028 | #else |
2022 | if(num_tracks_in_memory()) | 2029 | if(num_tracks_in_memory()) |
2023 | return &id3tags[tag_read_idx].id3; | 2030 | return &get_trackdata(0)->id3; |
2024 | else | 2031 | else |
2025 | return NULL; | 2032 | return NULL; |
2026 | #endif /* #ifdef SIMULATOR */ | 2033 | #endif /* #ifdef SIMULATOR */ |
@@ -2032,7 +2039,7 @@ struct mp3entry* audio_next_track() | |||
2032 | return &taginfo; | 2039 | return &taginfo; |
2033 | #else | 2040 | #else |
2034 | if(num_tracks_in_memory() > 1) | 2041 | if(num_tracks_in_memory() > 1) |
2035 | return &(id3tags[(tag_read_idx+1) & MAX_ID3_TAGS_MASK].id3); | 2042 | return &get_trackdata(1)->id3; |
2036 | else | 2043 | else |
2037 | return NULL; | 2044 | return NULL; |
2038 | #endif /* #ifdef SIMULATOR */ | 2045 | #endif /* #ifdef SIMULATOR */ |
@@ -2771,7 +2778,7 @@ void audio_init(void) | |||
2771 | create_thread(mpeg_thread, mpeg_stack, | 2778 | create_thread(mpeg_thread, mpeg_stack, |
2772 | sizeof(mpeg_stack), mpeg_thread_name); | 2779 | sizeof(mpeg_stack), mpeg_thread_name); |
2773 | 2780 | ||
2774 | memset(id3tags, sizeof(id3tags), 0); | 2781 | memset(trackdata, sizeof(trackdata), 0); |
2775 | 2782 | ||
2776 | #if CONFIG_HWCODEC == MAS3587F | 2783 | #if CONFIG_HWCODEC == MAS3587F |
2777 | if(read_hw_mask() & PR_ACTIVE_HIGH) | 2784 | if(read_hw_mask() & PR_ACTIVE_HIGH) |