summaryrefslogtreecommitdiff
path: root/firmware/mpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/mpeg.c')
-rw-r--r--firmware/mpeg.c143
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);
95extern void update_file_pos( int id, int pos ); 95extern 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
101struct id3tag 101struct 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
108static struct id3tag id3tags[MAX_ID3_TAGS]; 108static struct trackdata trackdata[MAX_TRACK_ENTRIES];
109 109
110static bool v1first = false; 110static 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
117static int tag_read_idx = 0; 117static int track_read_idx = 0;
118static int tag_write_idx = 0; 118static int track_write_idx = 0;
119 119
120static int num_tracks_in_memory(void) 120static 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
155static void remove_all_non_current_tags(void) 155static 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
161static void remove_all_tags(void) 161static 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
168static 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
169static void set_elapsed(struct mp3entry* id3) 177static 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
667void playback_tick(void) 673void 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
773static int add_track_to_tag_list(const char *filename) 781static 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
796static int new_file(int steps) 808static 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)
889static void update_playlist(void) 901static 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)