summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/codecs/mpa.c56
-rw-r--r--apps/dsp.c20
-rw-r--r--apps/playback.c96
-rw-r--r--apps/playback.h5
4 files changed, 139 insertions, 38 deletions
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c
index f2fd8a6e2b..a52dc12a40 100644
--- a/apps/codecs/mpa.c
+++ b/apps/codecs/mpa.c
@@ -57,15 +57,6 @@ extern char iramstart[];
57extern char iramend[]; 57extern char iramend[];
58#endif 58#endif
59 59
60/*
61long resample(long *in, long *out, int num, struct resampler *s)
62{
63 if (s->delta >= (1 << 16))
64 return downsample(in, out, num, s);
65 else
66 return upsample(in, out, num, s);
67}
68*/
69/* this is the codec entry point */ 60/* this is the codec entry point */
70enum codec_status codec_start(struct codec_api* api) 61enum codec_status codec_start(struct codec_api* api)
71{ 62{
@@ -79,9 +70,10 @@ enum codec_status codec_start(struct codec_api* api)
79 unsigned int samplesdone; 70 unsigned int samplesdone;
80 bool first_frame; 71 bool first_frame;
81 int stop_skip, start_skip; 72 int stop_skip, start_skip;
82 // struct resampler lr = { 0, 0, 0 }, rr = { 0, 0, 0 }; 73 int current_stereo_mode = -1;
74 int frequency_divider;
75
83 /* Generic codec inititialisation */ 76 /* Generic codec inititialisation */
84
85 TEST_CODEC_API(api); 77 TEST_CODEC_API(api);
86 78
87#ifdef USE_IRAM 79#ifdef USE_IRAM
@@ -102,7 +94,6 @@ enum codec_status codec_start(struct codec_api* api)
102 ci->configure(DSP_SET_CLIP_MAX, (int *)(MAD_F_ONE - 1)); 94 ci->configure(DSP_SET_CLIP_MAX, (int *)(MAD_F_ONE - 1));
103 ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(MAD_F_FRACBITS)); 95 ci->configure(DSP_SET_SAMPLE_DEPTH, (int *)(MAD_F_FRACBITS));
104 ci->configure(DSP_DITHER, (bool *)false); 96 ci->configure(DSP_DITHER, (bool *)false);
105 ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED);
106 ci->configure(CODEC_DSP_ENABLE, (bool *)true); 97 ci->configure(CODEC_DSP_ENABLE, (bool *)true);
107 98
108 ci->memset(&Stream, 0, sizeof(struct mad_stream)); 99 ci->memset(&Stream, 0, sizeof(struct mad_stream));
@@ -128,6 +119,7 @@ enum codec_status codec_start(struct codec_api* api)
128 first_frame = false; 119 first_frame = false;
129 file_end = 0; 120 file_end = 0;
130 OutputPtr = OutputBuffer; 121 OutputPtr = OutputBuffer;
122 frequency_divider = ci->id3->frequency / 100;
131 123
132 while (!*ci->taginfo_ready) 124 while (!*ci->taginfo_ready)
133 ci->yield(); 125 ci->yield();
@@ -154,16 +146,16 @@ enum codec_status codec_start(struct codec_api* api)
154 /* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3, 146 /* TODO: 1152 is the frame size in samples for MPEG1 layer 2 and layer 3,
155 it's probably not correct at all for MPEG2 and layer 1 */ 147 it's probably not correct at all for MPEG2 and layer 1 */
156 samplecount = info->frame_count*1152 - (start_skip + stop_skip); 148 samplecount = info->frame_count*1152 - (start_skip + stop_skip);
157 samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10; 149 samplesdone = ci->id3->elapsed * frequency_divider / 10;
158 } else { 150 } else {
159 samplecount = ci->id3->length * (ci->id3->frequency / 100) / 10; 151 samplecount = ci->id3->length * frequency_divider / 10;
160 samplesdone = ci->id3->elapsed * (ci->id3->frequency / 100) / 10; 152 samplesdone = ci->id3->elapsed * frequency_divider / 10;
161 } 153 }
162 154
163 /* This is the decoding loop. */ 155 /* This is the decoding loop. */
164 while (1) { 156 while (1) {
165 ci->yield(); 157 ci->yield();
166 if (ci->stop_codec || ci->reload_codec) { 158 if (ci->stop_codec || ci->reload_codec) {
167 break ; 159 break ;
168 } 160 }
169 161
@@ -171,11 +163,12 @@ enum codec_status codec_start(struct codec_api* api)
171 unsigned int sample_loc; 163 unsigned int sample_loc;
172 int newpos; 164 int newpos;
173 165
174 sample_loc = ci->seek_time/1000 * ci->id3->frequency; 166 sample_loc = ci->seek_time * frequency_divider / 10;
175 newpos = ci->mp3_get_filepos(ci->seek_time-1); 167 newpos = ci->mp3_get_filepos(ci->seek_time-1);
168 if (sample_loc >= samplecount + samplesdone)
169 break ;
170
176 if (ci->seek_buffer(newpos)) { 171 if (ci->seek_buffer(newpos)) {
177 if (sample_loc >= samplecount + samplesdone)
178 break ;
179 samplecount += samplesdone - sample_loc; 172 samplecount += samplesdone - sample_loc;
180 samplesdone = sample_loc; 173 samplesdone = sample_loc;
181 } 174 }
@@ -232,17 +225,28 @@ enum codec_status codec_start(struct codec_api* api)
232 /* We skip start_skip number of samples here, this should only happen for 225 /* We skip start_skip number of samples here, this should only happen for
233 very first frame in the stream. */ 226 very first frame in the stream. */
234 /* TODO: possible for start_skip to exceed one frames worth of samples? */ 227 /* TODO: possible for start_skip to exceed one frames worth of samples? */
235 //length = resample((long *)&Synth.pcm.samples[0][start_skip], resampled_data[0], Synth.pcm.length, &lr); 228
236 //if (MAD_NCHANNELS(&Frame.header) == 2) 229 if (MAD_NCHANNELS(&Frame.header) == 2) {
237 // resample((long *)&Synth.pcm.samples[1][start_skip], resampled_data[1], Synth.pcm.length, &rr); 230 if (current_stereo_mode != STEREO_NONINTERLEAVED) {
238 ci->audiobuffer_insert_split(&Synth.pcm.samples[0][start_skip], 231 ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_NONINTERLEAVED);
239 &Synth.pcm.samples[1][start_skip], 232 current_stereo_mode = STEREO_NONINTERLEAVED;
240 (Synth.pcm.length - start_skip) * 4); 233 }
234 ci->audiobuffer_insert_split(&Synth.pcm.samples[0][start_skip],
235 &Synth.pcm.samples[1][start_skip],
236 (Synth.pcm.length - start_skip) * 4);
237 } else {
238 if (current_stereo_mode != STEREO_MONO) {
239 ci->configure(DSP_SET_STEREO_MODE, (int *)STEREO_MONO);
240 current_stereo_mode = STEREO_MONO;
241 }
242 ci->audiobuffer_insert((char *)&Synth.pcm.samples[0][start_skip],
243 (Synth.pcm.length - start_skip) * 4);
244 }
241 start_skip = 0; /* not very elegant, and might want to keep this value */ 245 start_skip = 0; /* not very elegant, and might want to keep this value */
242 246
243 samplesdone += Synth.pcm.length; 247 samplesdone += Synth.pcm.length;
244 samplecount -= Synth.pcm.length; 248 samplecount -= Synth.pcm.length;
245 ci->set_elapsed(samplesdone / (ci->id3->frequency/1000)); 249 ci->set_elapsed(samplesdone / (frequency_divider / 10));
246 } 250 }
247 251
248 Stream.error = 0; 252 Stream.error = 0;
diff --git a/apps/dsp.c b/apps/dsp.c
index 56ebacb24c..b24e261371 100644
--- a/apps/dsp.c
+++ b/apps/dsp.c
@@ -269,7 +269,6 @@ void convert_stereo_mode(long *dest, long *src, int samplecount)
269 } 269 }
270} 270}
271 271
272/* Not yet functional. */
273void scale_up(long *dest, short *src, int samplecount) 272void scale_up(long *dest, short *src, int samplecount)
274{ 273{
275 int i; 274 int i;
@@ -287,8 +286,6 @@ void scale_up_convert_stereo_mode(long *dest, short *src, int samplecount)
287 for (i = 0; i < samplecount; i++) { 286 for (i = 0; i < samplecount; i++) {
288 dest[i] = (long)(src[i*2+0] << SAMPLE_DEPTH); 287 dest[i] = (long)(src[i*2+0] << SAMPLE_DEPTH);
289 dest[i+samplecount] = (long)(src[i*2+1] << SAMPLE_DEPTH); 288 dest[i+samplecount] = (long)(src[i*2+1] << SAMPLE_DEPTH);
290 //dest[i] = (long)(((src[i*2 + 0] << 8)&0x7fff) | ((1L << 31) & src[i*2+0]<<15));
291 //dest[i+samplecount] = (long)(((src[i*2 + 1] << 8)&0x7fff) | ((1L << 31) & src[i*2+1]<<15));
292 } 289 }
293} 290}
294 291
@@ -307,21 +304,22 @@ int dsp_process(char *dest, char *src, int samplecount)
307 p = src; 304 p = src;
308 /* Scale up to 32-bit samples. */ 305 /* Scale up to 32-bit samples. */
309 if (dsp_config.sample_depth <= SAMPLE_DEPTH) { 306 if (dsp_config.sample_depth <= SAMPLE_DEPTH) {
310 if (dsp_config.stereo_mode == STEREO_INTERLEAVED) 307 if (dsp_config.stereo_mode == STEREO_INTERLEAVED) {
311 scale_up_convert_stereo_mode((long *)samplebuf, 308 scale_up_convert_stereo_mode((long *)samplebuf,
312 (short *)p, copy_n); 309 (short *)p, copy_n);
313 else 310 } else {
314 scale_up((long *)samplebuf, (short *)p, copy_n); 311 scale_up((long *)samplebuf, (short *)p, copy_n);
312 }
315 p = samplebuf; 313 p = samplebuf;
316 fracbits = 31; 314 fracbits = 31;
317 } 315 }
318 316
319 /* Convert to non-interleaved stereo. */ 317 /* Convert to non-interleaved stereo. */
320 else if (dsp_config.stereo_mode == STEREO_INTERLEAVED) { 318 else if (dsp_config.stereo_mode == STEREO_INTERLEAVED) {
321 convert_stereo_mode((long *)samplebuf, (long *)p, copy_n); 319 convert_stereo_mode((long *)samplebuf, (long *)p, copy_n / 2);
322 p = samplebuf; 320 p = samplebuf;
323 } 321 }
324 322
325 /* Apply DSP functions. */ 323 /* Apply DSP functions. */
326 if (dsp_config.stereo_mode == STEREO_INTERLEAVED) { 324 if (dsp_config.stereo_mode == STEREO_INTERLEAVED) {
327 channel = 0; 325 channel = 0;
@@ -330,6 +328,12 @@ int dsp_process(char *dest, char *src, int samplecount)
330 channel = 1; 328 channel = 1;
331 process((short *)dest, (long *)p, copy_n / 2); 329 process((short *)dest, (long *)p, copy_n / 2);
332 dest += rc; 330 dest += rc;
331 } else if (dsp_config.stereo_mode == STEREO_MONO) {
332 channel = 0;
333 rc = process((short *)dest, (long *)p, copy_n) * 4;
334 channel = 1;
335 process((short *)dest, (long *)p, copy_n);
336 dest += rc;
333 } else { 337 } else {
334 rc = process((short *)dest, (long *)p, copy_n) * 2; 338 rc = process((short *)dest, (long *)p, copy_n) * 2;
335 dest += rc * 2; 339 dest += rc * 2;
diff --git a/apps/playback.c b/apps/playback.c
index 70cb36341b..3a5eeb328f 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -165,6 +165,8 @@ static int new_track;
165 165
166/* Callback function to call when current track has really changed. */ 166/* Callback function to call when current track has really changed. */
167void (*track_changed_callback)(struct track_info *ti); 167void (*track_changed_callback)(struct track_info *ti);
168void (*track_buffer_callback)(struct mp3entry *id3, bool last_track);
169void (*track_unbuffer_callback)(struct mp3entry *id3, bool disk_spinning);
168 170
169/* Configuration */ 171/* Configuration */
170static int conf_bufferlimit; 172static int conf_bufferlimit;
@@ -266,10 +268,14 @@ bool codec_audiobuffer_insert_callback(char *buf, long length)
266 int factor; 268 int factor;
267 int next_channel = 0; 269 int next_channel = 0;
268 int processed_length; 270 int processed_length;
271 int mono = 0;
269 272
270 /* If non-interleaved stereo mode. */ 273 /* If non-interleaved stereo mode. */
271 if (dsp_config.stereo_mode == STEREO_NONINTERLEAVED) { 274 if (dsp_config.stereo_mode == STEREO_NONINTERLEAVED)
272 next_channel = length / 2; 275 next_channel = length / 2;
276 else if (dsp_config.stereo_mode == STEREO_MONO) {
277 length *= 2;
278 mono = 1;
273 } 279 }
274 280
275 if (dsp_config.sample_depth > 16) { 281 if (dsp_config.sample_depth > 16) {
@@ -296,11 +302,11 @@ bool codec_audiobuffer_insert_callback(char *buf, long length)
296 processed_length = dsp_process(dest, buf, realsize / 4) * 2; 302 processed_length = dsp_process(dest, buf, realsize / 4) * 2;
297 dsp_process(dest, buf + next_channel, realsize / 4); 303 dsp_process(dest, buf + next_channel, realsize / 4);
298 } else { 304 } else {
299 processed_length = dsp_process(dest, buf, realsize / 2); 305 processed_length = dsp_process(dest, buf, realsize >> (mono + 1));
300 } 306 }
301 pcm_flush_buffer(processed_length); 307 pcm_flush_buffer(processed_length);
302 length -= realsize; 308 length -= realsize;
303 buf += realsize << factor; 309 buf += realsize << (factor + mono);
304 } 310 }
305 311
306 return true; 312 return true;
@@ -589,6 +595,18 @@ void codec_configure_callback(int setting, void *value)
589 } 595 }
590} 596}
591 597
598void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
599 bool last_track))
600{
601 track_buffer_callback = handler;
602}
603
604void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3,
605 bool disk_spinning))
606{
607 track_unbuffer_callback = handler;
608}
609
592void audio_set_track_changed_event(void (*handler)(struct track_info *ti)) 610void audio_set_track_changed_event(void (*handler)(struct track_info *ti))
593{ 611{
594 track_changed_callback = handler; 612 track_changed_callback = handler;
@@ -934,6 +952,10 @@ void audio_play_start(int offset)
934 last_peek_offset = 0; 952 last_peek_offset = 0;
935 if (audio_load_track(offset, true, 0)) { 953 if (audio_load_track(offset, true, 0)) {
936 last_peek_offset++; 954 last_peek_offset++;
955 if (track_buffer_callback) {
956 cur_ti->event_sent = true;
957 track_buffer_callback(&cur_ti->id3, true);
958 }
937 ata_sleep(); 959 ata_sleep();
938 } else { 960 } else {
939 logf("Failure"); 961 logf("Failure");
@@ -950,10 +972,46 @@ void audio_clear_track_entries(void)
950 for (i = 0; i < MAX_TRACK - track_count; i++) { 972 for (i = 0; i < MAX_TRACK - track_count; i++) {
951 if (++cur_idx >= MAX_TRACK) 973 if (++cur_idx >= MAX_TRACK)
952 cur_idx = 0; 974 cur_idx = 0;
975
976 /* Send event to notify that track has finished. */
977 if (track_unbuffer_callback && tracks[cur_idx].event_sent)
978 track_unbuffer_callback(&tracks[cur_idx].id3, filling);
953 memset(&tracks[cur_idx], 0, sizeof(struct track_info)); 979 memset(&tracks[cur_idx], 0, sizeof(struct track_info));
954 } 980 }
955} 981}
956 982
983/* Send callback events to notify about new tracks. */
984static void generate_postbuffer_events(void)
985{
986 int i;
987 int cur_ridx, event_count;
988
989 if (!track_buffer_callback)
990 return ;
991
992 /* At first determine how many unsent events we have. */
993 cur_ridx = track_ridx;
994 event_count = 0;
995 for (i = 0; i < track_count; i++) {
996 if (!tracks[cur_ridx].event_sent)
997 event_count++;
998 if (++cur_ridx >= MAX_TRACK)
999 cur_ridx -= MAX_TRACK;
1000 }
1001
1002 /* Now sent these events. */
1003 cur_ridx = track_ridx;
1004 for (i = 0; i < track_count; i++) {
1005 if (!tracks[cur_ridx].event_sent) {
1006 tracks[cur_ridx].event_sent = true;
1007 event_count--;
1008 track_buffer_callback(&tracks[cur_ridx].id3, event_count == 0);
1009 }
1010 if (++cur_ridx >= MAX_TRACK)
1011 cur_ridx -= MAX_TRACK;
1012 }
1013}
1014
957void initialize_buffer_fill(void) 1015void initialize_buffer_fill(void)
958{ 1016{
959 int cur_idx, i; 1017 int cur_idx, i;
@@ -1014,6 +1072,7 @@ void audio_check_buffer(void)
1014 if (audio_load_track(0, false, last_peek_offset)) { 1072 if (audio_load_track(0, false, last_peek_offset)) {
1015 last_peek_offset++; 1073 last_peek_offset++;
1016 } else if (tracks[track_widx].filerem == 0 || fill_bytesleft == 0) { 1074 } else if (tracks[track_widx].filerem == 0 || fill_bytesleft == 0) {
1075 generate_postbuffer_events();
1017 filling = false; 1076 filling = false;
1018 conf_bufferlimit = 0; 1077 conf_bufferlimit = 0;
1019 pcm_set_boost_mode(false); 1078 pcm_set_boost_mode(false);
@@ -1069,6 +1128,8 @@ void audio_change_track(void)
1069 logf("No more tracks"); 1128 logf("No more tracks");
1070 while (pcm_is_playing()) 1129 while (pcm_is_playing())
1071 yield(); 1130 yield();
1131 track_count = 0;
1132 audio_clear_track_entries();
1072 playing = false; 1133 playing = false;
1073 return ; 1134 return ;
1074 } 1135 }
@@ -1206,6 +1267,8 @@ void audio_thread(void)
1206 } 1267 }
1207 pcm_play_stop(); 1268 pcm_play_stop();
1208 pcm_play_pause(true); 1269 pcm_play_pause(true);
1270 track_count = 0;
1271 audio_clear_track_entries();
1209 break ; 1272 break ;
1210 1273
1211 case AUDIO_PAUSE: 1274 case AUDIO_PAUSE:
@@ -1233,6 +1296,8 @@ void audio_thread(void)
1233 1296
1234#ifndef SIMULATOR 1297#ifndef SIMULATOR
1235 case SYS_USB_CONNECTED: 1298 case SYS_USB_CONNECTED:
1299 track_count = 0;
1300 audio_clear_track_entries();
1236 playing = false; 1301 playing = false;
1237 filling = false; 1302 filling = false;
1238 ci.stop_codec = true; 1303 ci.stop_codec = true;
@@ -1269,6 +1334,8 @@ void codec_thread(void)
1269 codecsize = cur_ti->codecsize; 1334 codecsize = cur_ti->codecsize;
1270 if (codecsize == 0) { 1335 if (codecsize == 0) {
1271 logf("Codec slot is empty!"); 1336 logf("Codec slot is empty!");
1337 track_count = 0;
1338 audio_clear_track_entries();
1272 playing = false; 1339 playing = false;
1273 break ; 1340 break ;
1274 } 1341 }
@@ -1296,6 +1363,8 @@ void codec_thread(void)
1296 if (status != CODEC_OK) { 1363 if (status != CODEC_OK) {
1297 logf("Codec failure"); 1364 logf("Codec failure");
1298 splash(HZ*2, true, "Codec failure"); 1365 splash(HZ*2, true, "Codec failure");
1366 track_count = 0;
1367 audio_clear_track_entries();
1299 playing = false; 1368 playing = false;
1300 } else { 1369 } else {
1301 logf("Codec finished"); 1370 logf("Codec finished");
@@ -1597,6 +1666,18 @@ void mpeg_id3_options(bool _v1first)
1597 v1first = _v1first; 1666 v1first = _v1first;
1598} 1667}
1599 1668
1669/*
1670void test_buffer_event(struct mp3entry *id3, bool last_track)
1671{
1672 logf("be:%d%s", last_track, id3->title);
1673}
1674
1675void test_unbuffer_event(struct mp3entry *id3, bool disk_spinning)
1676{
1677 logf("ube:%d%s", disk_spinning, id3->title);
1678}
1679*/
1680
1600void audio_init(void) 1681void audio_init(void)
1601{ 1682{
1602 logf("audio api init"); 1683 logf("audio api init");
@@ -1611,12 +1692,19 @@ void audio_init(void)
1611 paused = false; 1692 paused = false;
1612 track_changed = false; 1693 track_changed = false;
1613 current_fd = -1; 1694 current_fd = -1;
1695 track_buffer_callback = NULL;
1696 track_unbuffer_callback = NULL;
1614 track_changed_callback = NULL; 1697 track_changed_callback = NULL;
1615 1698
1616 logf("abuf:%0x", PCMBUF_SIZE); 1699 logf("abuf:%0x", PCMBUF_SIZE);
1617 logf("fbuf:%0x", codecbuflen); 1700 logf("fbuf:%0x", codecbuflen);
1618 logf("mbuf:%0x", MALLOC_BUFSIZE); 1701 logf("mbuf:%0x", MALLOC_BUFSIZE);
1619 1702
1703 /*
1704 audio_set_track_buffer_event(test_buffer_event);
1705 audio_set_track_unbuffer_event(test_unbuffer_event);
1706 */
1707
1620 /* Initialize codec api. */ 1708 /* Initialize codec api. */
1621 ci.read_filebuf = codec_filebuf_callback; 1709 ci.read_filebuf = codec_filebuf_callback;
1622 ci.audiobuffer_insert = pcm_insert_buffer; 1710 ci.audiobuffer_insert = pcm_insert_buffer;
diff --git a/apps/playback.h b/apps/playback.h
index 5cebfa84b3..8148a3445c 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -58,10 +58,15 @@ struct track_info {
58 volatile int available; /* Available bytes to read from buffer */ 58 volatile int available; /* Available bytes to read from buffer */
59 bool taginfo_ready; /* Is metadata read */ 59 bool taginfo_ready; /* Is metadata read */
60 int playlist_offset; /* File location in playlist */ 60 int playlist_offset; /* File location in playlist */
61 bool event_sent; /* Has event callback functions been called? */
61}; 62};
62 63
63/* Functions */ 64/* Functions */
64void audio_set_track_changed_event(void (*handler)(struct track_info *ti)); 65void audio_set_track_changed_event(void (*handler)(struct track_info *ti));
66void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3,
67 bool last_track));
68void audio_set_track_unbufer_event(void (*handler)(struct mp3entry *id3,
69 bool disk_spinning));
65void audio_invalidate_tracks(void); 70void audio_invalidate_tracks(void);
66 71
67#endif 72#endif