summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/onplay.c130
-rw-r--r--firmware/export/mp3data.h1
-rw-r--r--firmware/mp3data.c41
-rw-r--r--firmware/mpeg.c43
4 files changed, 118 insertions, 97 deletions
diff --git a/apps/onplay.c b/apps/onplay.c
index ceaae2c238..3ba4c1b49c 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -210,14 +210,15 @@ static const unsigned char empty_id3_header[] =
210 210
211static bool vbr_fix(void) 211static bool vbr_fix(void)
212{ 212{
213 unsigned char xingbuf[417]; 213 unsigned char xingbuf[1500];
214 struct mp3entry entry; 214 struct mp3entry entry;
215 int fd; 215 int fd;
216 int rc; 216 int rc;
217 int flen; 217 int flen;
218 int num_frames; 218 int num_frames;
219 int fpos;
220 int numbytes; 219 int numbytes;
220 int framelen;
221 int unused_space;
221 222
222 if(mpeg_status()) { 223 if(mpeg_status()) {
223 splash(HZ*2, 0, true, str(LANG_VBRFIX_STOP_PLAY)); 224 splash(HZ*2, 0, true, str(LANG_VBRFIX_STOP_PLAY));
@@ -250,26 +251,45 @@ static bool vbr_fix(void)
250 flen, xingupdate); 251 flen, xingupdate);
251 252
252 if(num_frames) { 253 if(num_frames) {
253 create_xing_header(fd, entry.first_frame_offset, 254 /* Note: We don't need to pass any values for mpeg_version and
254 flen, xingbuf, num_frames, xingupdate, true); 255 sample_rate because they will be extracted from the mpeg stream */
256 framelen = create_xing_header(fd, entry.first_frame_offset,
257 flen, xingbuf, num_frames,
258 0, 0, xingupdate, true);
255 259
256 /* Try to fit the Xing header first in the stream. Replace the existing 260 /* Try to fit the Xing header first in the stream. Replace the existing
257 Xing header if there is one, else see if there is room between the 261 VBR header if there is one, else see if there is room between the
258 ID3 tag and the first MP3 frame. */ 262 ID3 tag and the first MP3 frame. */
259 if(entry.vbr_header_pos) { 263 if(entry.first_frame_offset - entry.id3v2len >=
260 /* Reuse existing Xing header */ 264 (unsigned int)framelen) {
261 fpos = entry.vbr_header_pos; 265 DEBUGF("Using existing space between ID3 and first frame\n");
262 266
263 DEBUGF("Reusing Xing header at %d\n", fpos); 267 /* Seek to the beginning of the unused space */
264 268 rc = lseek(fd, entry.id3v2len, SEEK_SET);
265 rc = lseek(fd, entry.vbr_header_pos, SEEK_SET);
266 if(rc < 0) { 269 if(rc < 0) {
267 close(fd); 270 close(fd);
268 fileerror(rc); 271 fileerror(rc);
269 return true; 272 return true;
270 } 273 }
274
275 unused_space =
276 entry.first_frame_offset - entry.id3v2len - framelen;
271 277
272 rc = write(fd, xingbuf, 417); 278 /* Fill the unused space with 0's (using the MP3 buffer)
279 and write it to the file */
280 if(unused_space)
281 {
282 memset(mp3buf, 0, unused_space);
283 rc = write(fd, mp3buf, unused_space);
284 if(rc < 0) {
285 close(fd);
286 fileerror(rc);
287 return true;
288 }
289 }
290
291 /* Then write the Xing header */
292 rc = write(fd, xingbuf, framelen);
273 if(rc < 0) { 293 if(rc < 0) {
274 close(fd); 294 close(fd);
275 fileerror(rc); 295 fileerror(rc);
@@ -278,61 +298,41 @@ static bool vbr_fix(void)
278 298
279 close(fd); 299 close(fd);
280 } else { 300 } else {
281 /* Any room between ID3 tag and first MP3 frame? */ 301 /* If not, insert some space. If there is an ID3 tag in the
282 if(entry.first_frame_offset - entry.id3v2len > 417) { 302 file we only insert just enough to squeeze the Xing header
283 DEBUGF("Using existing space between ID3 and first frame\n"); 303 in. If not, we insert an additional empty ID3 tag of 4K. */
284 rc = lseek(fd, entry.first_frame_offset - 417, SEEK_SET); 304
285 if(rc < 0) { 305 close(fd);
286 close(fd); 306
287 fileerror(rc); 307 /* Nasty trick alert! The insert_data_in_file() function
288 return true; 308 uses the MP3 buffer when copying the data. We assume
289 } 309 that the ID3 tag isn't longer than 1MB so the xing
290 310 buffer won't be overwritten. */
291 rc = write(fd, xingbuf, 417); 311
292 if(rc < 0) { 312 if(entry.first_frame_offset) {
293 close(fd); 313 DEBUGF("Inserting %d bytes\n", framelen);
294 fileerror(rc); 314 numbytes = framelen;
295 return true;
296 }
297
298 close(fd);
299 } else { 315 } else {
300 /* If not, insert some space. If there is an ID3 tag in the 316 DEBUGF("Inserting 4096+%d bytes\n", framelen);
301 file we only insert just enough to squeeze the Xing header 317 numbytes = 4096 + framelen;
302 in. If not, we insert an additional empty ID3 tag of 4K. */
303
304 close(fd);
305
306 /* Nasty trick alert! The insert_data_in_file() function
307 uses the MP3 buffer when copying the data. We assume
308 that the ID3 tag isn't longer than 1MB so the xing
309 buffer won't be overwritten. */
310
311 if(entry.first_frame_offset) {
312 DEBUGF("Inserting 417 bytes\n");
313 numbytes = 417;
314 } else {
315 DEBUGF("Inserting 4096+417 bytes\n");
316 numbytes = 4096 + 417;
317
318 memset(mp3buf + 0x100000, 0, numbytes);
319
320 /* Insert the ID3 header */
321 memcpy(mp3buf + 0x100000, empty_id3_header,
322 sizeof(empty_id3_header));
323 }
324
325 /* Copy the Xing header */
326 memcpy(mp3buf + 0x100000 + numbytes - 417, xingbuf, 417);
327 318
328 rc = insert_data_in_file(selected_file, 319 memset(mp3buf + 0x100000, 0, numbytes);
329 entry.first_frame_offset,
330 mp3buf + 0x100000, numbytes);
331 320
332 if(rc < 0) { 321 /* Insert the ID3 header */
333 fileerror(rc); 322 memcpy(mp3buf + 0x100000, empty_id3_header,
334 return true; 323 sizeof(empty_id3_header));
335 } 324 }
325
326 /* Copy the Xing header */
327 memcpy(mp3buf + 0x100000 + numbytes - framelen, xingbuf, framelen);
328
329 rc = insert_data_in_file(selected_file,
330 entry.first_frame_offset,
331 mp3buf + 0x100000, numbytes);
332
333 if(rc < 0) {
334 fileerror(rc);
335 return true;
336 } 336 }
337 } 337 }
338 338
diff --git a/firmware/export/mp3data.h b/firmware/export/mp3data.h
index 54a6899a78..d180935aa4 100644
--- a/firmware/export/mp3data.h
+++ b/firmware/export/mp3data.h
@@ -61,6 +61,7 @@ int count_mp3_frames(int fd, int startpos, int filesize,
61 void (*progressfunc)(int)); 61 void (*progressfunc)(int));
62int create_xing_header(int fd, int startpos, int filesize, 62int create_xing_header(int fd, int startpos, int filesize,
63 unsigned char *buf, int num_frames, 63 unsigned char *buf, int num_frames,
64 int mpeg_version, int sample_rate,
64 void (*progressfunc)(int), bool generate_toc); 65 void (*progressfunc)(int), bool generate_toc);
65 66
66#endif 67#endif
diff --git a/firmware/mp3data.c b/firmware/mp3data.c
index 28f2cb27f3..98dff50442 100644
--- a/firmware/mp3data.c
+++ b/firmware/mp3data.c
@@ -35,7 +35,7 @@
35#include "mp3data.h" 35#include "mp3data.h"
36#include "file.h" 36#include "file.h"
37 37
38#undef DEBUG_VERBOSE 38#define DEBUG_VERBOSE
39 39
40#define BYTES2INT(b1,b2,b3,b4) (((b1 & 0xFF) << (3*8)) | \ 40#define BYTES2INT(b1,b2,b3,b4) (((b1 & 0xFF) << (3*8)) | \
41 ((b2 & 0xFF) << (2*8)) | \ 41 ((b2 & 0xFF) << (2*8)) | \
@@ -530,9 +530,10 @@ int get_mp3file_info(int fd, struct mp3info *info)
530 return bytecount; 530 return bytecount;
531} 531}
532 532
533/* This is an MP3 header, 128kbit/s, 44.1kHz, with silence */ 533/* This is an MP3 header, 128kbit/s, with silence
534 MPEG version and sample frequency are not set */
534static const unsigned char xing_frame_header[] = { 535static const unsigned char xing_frame_header[] = {
535 0xff, 0xfa, 0x90, 0x64, 0x86, 0x1f 536 0xff, 0xe2, 0x90, 0x64, 0x86, 0x1f
536}; 537};
537 538
538static const char cooltext[] = "Rockbox rocks"; 539static const char cooltext[] = "Rockbox rocks";
@@ -601,11 +602,15 @@ int count_mp3_frames(int fd, int startpos, int filesize,
601 } 602 }
602} 603}
603 604
605/* Note: mpeg_version and sample_rate are 2-bit values, as specified by the
606 MPEG frame standard. See the tables above. */
604int create_xing_header(int fd, int startpos, int filesize, 607int create_xing_header(int fd, int startpos, int filesize,
605 unsigned char *buf, int num_frames, 608 unsigned char *buf, int num_frames,
609 int mpeg_version, int sample_rate,
606 void (*progressfunc)(int), bool generate_toc) 610 void (*progressfunc)(int), bool generate_toc)
607{ 611{
608 unsigned long header = 0; 612 unsigned long header = 0;
613 unsigned long saved_header;
609 struct mp3info info; 614 struct mp3info info;
610 int pos, last_pos; 615 int pos, last_pos;
611 int i, j; 616 int i, j;
@@ -618,9 +623,9 @@ int create_xing_header(int fd, int startpos, int filesize,
618 DEBUGF("create_xing_header()\n"); 623 DEBUGF("create_xing_header()\n");
619 624
620 /* Create the frame header */ 625 /* Create the frame header */
621 memset(buf, 0, 417); 626 memset(buf, 0, 1500);
622 memcpy(buf, xing_frame_header, 6); 627 memcpy(buf, xing_frame_header, 6);
623 628
624 lseek(fd, startpos, SEEK_SET); 629 lseek(fd, startpos, SEEK_SET);
625 buf_init(); 630 buf_init();
626 631
@@ -664,6 +669,10 @@ int create_xing_header(int fd, int startpos, int filesize,
664 buf_seek(fd, info.frame_size-4); 669 buf_seek(fd, info.frame_size-4);
665 filepos += info.frame_size; 670 filepos += info.frame_size;
666 } 671 }
672
673 /* Save one header for later use */
674 if(i == 1)
675 saved_header = header;
667 676
668 if(progressfunc) 677 if(progressfunc)
669 { 678 {
@@ -684,6 +693,26 @@ int create_xing_header(int fd, int startpos, int filesize,
684 693
685 memcpy(buf + index + 100, cooltext, sizeof(cooltext)); 694 memcpy(buf + index + 100, cooltext, sizeof(cooltext));
686 695
696 /* We must fill in the correct sample rate and mpeg version. If the TOC
697 should be generated, we take that data from the actual stream. If not,
698 we use the supplied parameters. */
699 if(generate_toc)
700 {
701 saved_header &= (VERSION_MASK | SAMPLERATE_MASK);
702
703 buf[1] |= (saved_header >> 16) & 0xff;
704 buf[2] |= (saved_header >> 8) & 0xff;
705 }
706 else
707 {
708 buf[1] |= mpeg_version << 3;
709 buf[2] |= sample_rate << 2;
710 }
711
712 /* Now get the length of the newly created frame */
713 header = BYTES2INT(buf[0], buf[1], buf[2], buf[3]);
714 mp3headerinfo(&info, header);
715
687#ifdef DEBUG 716#ifdef DEBUG
688 for(i = 0;i < 417;i++) 717 for(i = 0;i < 417;i++)
689 { 718 {
@@ -694,5 +723,5 @@ int create_xing_header(int fd, int startpos, int filesize,
694 } 723 }
695#endif 724#endif
696 725
697 return 0; 726 return info.frame_size;
698} 727}
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 85f9c72a25..7e48040da2 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -489,7 +489,8 @@ unsigned long record_start_time; /* Value of current_tick when recording
489 was started */ 489 was started */
490static bool saving; /* We are saving the buffer to disk */ 490static bool saving; /* We are saving the buffer to disk */
491static char recording_filename[MAX_PATH]; 491static char recording_filename[MAX_PATH];
492 492static int rec_frequency_index; /* For create_xing_header() calls */
493static int rec_version_index; /* For create_xing_header() calls */
493#endif 494#endif
494 495
495static int mpeg_file; 496static int mpeg_file;
@@ -1010,13 +1011,6 @@ void IRQ3(void)
1010 dma_tick(); 1011 dma_tick();
1011 else 1012 else
1012 postpone_dma_tick(); 1013 postpone_dma_tick();
1013
1014#if 0
1015 if(mpeg_mode == MPEG_ENCODER)
1016 /* Shut off if recording is stopped */
1017 if(!is_recording)
1018 demand_irq_enable(false);
1019#endif
1020} 1014}
1021#endif 1015#endif
1022 1016
@@ -1271,6 +1265,7 @@ static void mpeg_thread(void)
1271#ifdef HAVE_MAS3587F 1265#ifdef HAVE_MAS3587F
1272 int amount_to_save; 1266 int amount_to_save;
1273 int writelen; 1267 int writelen;
1268 int framelen;
1274#endif 1269#endif
1275 1270
1276 is_playing = false; 1271 is_playing = false;
@@ -1734,15 +1729,6 @@ static void mpeg_thread(void)
1734 DEBUGF("R\n"); 1729 DEBUGF("R\n");
1735 t1 = current_tick; 1730 t1 = current_tick;
1736 len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read); 1731 len = read(mpeg_file, mp3buf+mp3buf_write, amount_to_read);
1737#if 0
1738 if(id3tags[tag_read_idx]->id3.vbr)
1739 /* Average bitrate * 1.5 */
1740 recalculate_watermark(
1741 (id3tags[tag_read_idx]->id3.bitrate * 3) / 2);
1742 else
1743 recalculate_watermark(
1744 id3tags[tag_read_idx]->id3.bitrate);
1745#endif
1746 if(len > 0) 1732 if(len > 0)
1747 { 1733 {
1748 t2 = current_tick; 1734 t2 = current_tick;
@@ -1854,10 +1840,10 @@ static void mpeg_thread(void)
1854 DEBUGF("Recording...\n"); 1840 DEBUGF("Recording...\n");
1855 reset_mp3_buffer(); 1841 reset_mp3_buffer();
1856 1842
1857 /* Advance the write pointer 4096+417 bytes to make 1843 /* Advance the write pointer 4096+1500 bytes to make
1858 room for an ID3 tag plus a VBR header */ 1844 room for an ID3 tag plus a VBR header */
1859 mp3buf_write = 4096+417; 1845 mp3buf_write = 4096+1500;
1860 memset(mp3buf, 0, 4096+417); 1846 memset(mp3buf, 0, 4096+1500);
1861 1847
1862 /* Insert the ID3 header */ 1848 /* Insert the ID3 header */
1863 memcpy(mp3buf, empty_id3_header, sizeof(empty_id3_header)); 1849 memcpy(mp3buf, empty_id3_header, sizeof(empty_id3_header));
@@ -1898,12 +1884,14 @@ static void mpeg_thread(void)
1898 if(num_recorded_frames == 0x7ffff) 1884 if(num_recorded_frames == 0x7ffff)
1899 num_recorded_frames = 0; 1885 num_recorded_frames = 0;
1900 1886
1901 create_xing_header(mpeg_file, 0, num_rec_bytes, 1887 framelen = create_xing_header(mpeg_file, 0, num_rec_bytes,
1902 mp3buf, num_recorded_frames, NULL, 1888 mp3buf, num_recorded_frames,
1903 false); 1889 rec_version_index,
1890 rec_frequency_index,
1891 NULL, false);
1904 1892
1905 lseek(mpeg_file, 4096, SEEK_SET); 1893 lseek(mpeg_file, 4096+1500-framelen, SEEK_SET);
1906 write(mpeg_file, mp3buf, 417); 1894 write(mpeg_file, mp3buf, framelen);
1907 close(mpeg_file); 1895 close(mpeg_file);
1908 1896
1909 mpeg_file = -1; 1897 mpeg_file = -1;
@@ -2841,9 +2829,12 @@ void mpeg_set_recording_options(int frequency, int quality,
2841 unsigned long val; 2829 unsigned long val;
2842 2830
2843 is_mpeg1 = (frequency < 3)?true:false; 2831 is_mpeg1 = (frequency < 3)?true:false;
2832
2833 rec_version_index = is_mpeg1?3:2;
2834 rec_frequency_index = frequency % 3;
2844 2835
2845 val = (quality << 17) | 2836 val = (quality << 17) |
2846 ((frequency % 3) << 10) | 2837 (rec_frequency_index << 10) |
2847 ((is_mpeg1?1:0) << 9) | 2838 ((is_mpeg1?1:0) << 9) |
2848 (1 << 8) | /* CRC on */ 2839 (1 << 8) | /* CRC on */
2849 (((channel_mode * 2 + 1) & 3) << 6) | 2840 (((channel_mode * 2 + 1) & 3) << 6) |