summaryrefslogtreecommitdiff
path: root/firmware/mpeg.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/mpeg.c')
-rw-r--r--firmware/mpeg.c320
1 files changed, 198 insertions, 122 deletions
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 9470e7d84b..92f11e1b84 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -26,6 +26,7 @@
26#include "string.h" 26#include "string.h"
27#include <kernel.h> 27#include <kernel.h>
28#include "thread.h" 28#include "thread.h"
29#include "mp3data.h"
29#ifndef SIMULATOR 30#ifndef SIMULATOR
30#include "i2c.h" 31#include "i2c.h"
31#include "mas.h" 32#include "mas.h"
@@ -302,7 +303,7 @@ static void remove_all_tags(void)
302static void set_elapsed(struct mp3entry* id3) 303static void set_elapsed(struct mp3entry* id3)
303{ 304{
304 if ( id3->vbr ) { 305 if ( id3->vbr ) {
305 if ( id3->vbrflags & VBR_TOC_FLAG ) { 306 if ( id3->has_toc ) {
306 /* calculate elapsed time using TOC */ 307 /* calculate elapsed time using TOC */
307 int i; 308 int i;
308 unsigned int remainder, plen, relpos, nextpos; 309 unsigned int remainder, plen, relpos, nextpos;
@@ -1482,7 +1483,7 @@ static void mpeg_thread(void)
1482 1483
1483 if (id3->vbr) 1484 if (id3->vbr)
1484 { 1485 {
1485 if (id3->vbrflags & VBR_TOC_FLAG) 1486 if (id3->has_toc)
1486 { 1487 {
1487 /* Use the TOC to find the new position */ 1488 /* Use the TOC to find the new position */
1488 unsigned int percent, remainder; 1489 unsigned int percent, remainder;
@@ -1528,10 +1529,10 @@ static void mpeg_thread(void)
1528 transition properly to the next song */ 1529 transition properly to the next song */
1529 newpos = id3->filesize - id3->id3v1len - 1; 1530 newpos = id3->filesize - id3->id3v1len - 1;
1530 } 1531 }
1531 else if (newpos < (int)id3->id3v2len) 1532 else if (newpos < (int)id3->first_frame_offset)
1532 { 1533 {
1533 /* skip past id3v2 tag */ 1534 /* skip past id3v2 tag and other leading garbage */
1534 newpos = id3->id3v2len; 1535 newpos = id3->first_frame_offset;
1535 } 1536 }
1536 1537
1537 if (mpeg_file >= 0) 1538 if (mpeg_file >= 0)
@@ -1720,7 +1721,7 @@ static void mpeg_thread(void)
1720 t2 = current_tick; 1721 t2 = current_tick;
1721 DEBUGF("time: %d\n", t2 - t1); 1722 DEBUGF("time: %d\n", t2 - t1);
1722 DEBUGF("R: %x\n", len); 1723 DEBUGF("R: %x\n", len);
1723 1724
1724 /* Now make sure that we don't feed the MAS with ID3V1 1725 /* Now make sure that we don't feed the MAS with ID3V1
1725 data */ 1726 data */
1726 if (len < amount_to_read) 1727 if (len < amount_to_read)
@@ -1734,19 +1735,19 @@ static void mpeg_thread(void)
1734 { 1735 {
1735 if(tagptr >= mp3buflen) 1736 if(tagptr >= mp3buflen)
1736 tagptr -= mp3buflen; 1737 tagptr -= mp3buflen;
1737 1738
1738 if(mp3buf[tagptr] != tag[i]) 1739 if(mp3buf[tagptr] != tag[i])
1739 taglen = 0; 1740 taglen = 0;
1740 1741
1741 tagptr++; 1742 tagptr++;
1742 } 1743 }
1743 1744
1744 if(taglen) 1745 if(taglen)
1745 { 1746 {
1746 /* Skip id3v1 tag */ 1747 /* Skip id3v1 tag */
1747 DEBUGF("Skipping ID3v1 tag\n"); 1748 DEBUGF("Skipping ID3v1 tag\n");
1748 len -= taglen; 1749 len -= taglen;
1749 1750
1750 /* The very rare case when the entire tag 1751 /* The very rare case when the entire tag
1751 wasn't read in this read() call must be 1752 wasn't read in this read() call must be
1752 taken care of */ 1753 taken care of */
@@ -1819,131 +1820,135 @@ static void mpeg_thread(void)
1819 } 1820 }
1820 else 1821 else
1821 { 1822 {
1822 /* This doesn't look neccessary... 1823 queue_wait(&mpeg_queue, &ev);
1823 yield(); 1824 switch(ev.id)
1824 if(!queue_empty(&mpeg_queue)) 1825 {
1825 {*/ 1826 case MPEG_RECORD:
1826 queue_wait(&mpeg_queue, &ev); 1827 DEBUGF("Recording...\n");
1827 switch(ev.id) 1828 reset_mp3_buffer();
1828 {
1829 case MPEG_RECORD:
1830 DEBUGF("Recording...\n");
1831 reset_mp3_buffer();
1832 start_recording();
1833 demand_irq_enable(true);
1834 mpeg_file = creat(recording_filename, O_WRONLY);
1835
1836 if(mpeg_file < 0)
1837 panicf("recfile: %d", mpeg_file);
1838
1839 close(mpeg_file);
1840 mpeg_file = -1;
1841 break;
1842
1843 case MPEG_STOP:
1844 DEBUGF("MPEG_STOP\n");
1845 demand_irq_enable(false);
1846 stop_recording();
1847
1848 /* Save the remaining data in the buffer */
1849 stop_pending = true;
1850 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1851 break;
1852 1829
1853 case MPEG_STOP_DONE: 1830 /* Advance the write pointer 4096+417 bytes to make
1854 DEBUGF("MPEG_STOP_DONE\n"); 1831 room for an ID3 tag plus a VBR header */
1832 mp3buf_write = 4096+417;
1833 memset(mp3buf, 0, 4096+417);
1855 1834
1856 if(mpeg_file >= 0) 1835 start_recording();
1857 close(mpeg_file); 1836 demand_irq_enable(true);
1858 mpeg_file = -1; 1837
1838 mpeg_file = creat(recording_filename, O_WRONLY);
1839
1840 if(mpeg_file < 0)
1841 panicf("recfile: %d", mpeg_file);
1859 1842
1843
1844 close(mpeg_file);
1845
1846 mpeg_file = -1;
1847 break;
1848
1849 case MPEG_STOP:
1850 DEBUGF("MPEG_STOP\n");
1851 demand_irq_enable(false);
1852 stop_recording();
1853
1854 /* Save the remaining data in the buffer */
1855 stop_pending = true;
1856 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1857 break;
1858
1859 case MPEG_STOP_DONE:
1860 DEBUGF("MPEG_STOP_DONE\n");
1861
1862 if(mpeg_file >= 0)
1863 close(mpeg_file);
1864 mpeg_file = -1;
1865
1860#ifdef DEBUG1 1866#ifdef DEBUG1
1867 {
1868 int i;
1869 for(i = 0;i < 512;i++)
1861 { 1870 {
1862 int i; 1871 DEBUGF("%d - %d us (%d bytes)\n",
1863 for(i = 0;i < 512;i++) 1872 timing_info[i*2],
1864 { 1873 (timing_info[i*2+1] & 0xffff) *
1865 DEBUGF("%d - %d us (%d bytes)\n", 1874 10000 / 13824,
1866 timing_info[i*2], 1875 timing_info[i*2+1] >> 16);
1867 (timing_info[i*2+1] & 0xffff) *
1868 10000 / 13824,
1869 timing_info[i*2+1] >> 16);
1870 }
1871 } 1876 }
1877 }
1872#endif 1878#endif
1873 mpeg_stop_done = true; 1879 mpeg_stop_done = true;
1874 break; 1880 break;
1875 1881
1876 case MPEG_SAVE_DATA: 1882 case MPEG_SAVE_DATA:
1877 amount_to_save = mp3buf_write - mp3buf_read; 1883 amount_to_save = mp3buf_write - mp3buf_read;
1878 1884
1879 /* If the result is negative, the write index has 1885 /* If the result is negative, the write index has
1880 wrapped */ 1886 wrapped */
1881 if(amount_to_save < 0) 1887 if(amount_to_save < 0)
1882 { 1888 {
1883 amount_to_save += mp3buflen; 1889 amount_to_save += mp3buflen;
1884 } 1890 }
1885 1891
1886 DEBUGF("r: %x w: %x\n", mp3buf_read, mp3buf_write); 1892 DEBUGF("r: %x w: %x\n", mp3buf_read, mp3buf_write);
1887 DEBUGF("ats: %x\n", amount_to_save); 1893 DEBUGF("ats: %x\n", amount_to_save);
1888 /* Save data only if the buffer is getting full, 1894 /* Save data only if the buffer is getting full,
1889 or if we should stop recording */ 1895 or if we should stop recording */
1890 if(amount_to_save) 1896 if(amount_to_save)
1897 {
1898 if(mp3buflen - amount_to_save < MPEG_LOW_WATER ||
1899 stop_pending)
1891 { 1900 {
1892 if(mp3buflen - amount_to_save < MPEG_LOW_WATER || 1901 int rc;
1893 stop_pending) 1902
1894 { 1903 /* Only save up to the end of the buffer */
1895 int rc; 1904 writelen = MIN(amount_to_save,
1896 1905 mp3buflen - mp3buf_read);
1897 /* Only save up to the end of the buffer */ 1906
1898 writelen = MIN(amount_to_save, 1907 DEBUGF("wrl: %x\n", writelen);
1899 mp3buflen - mp3buf_read); 1908 mpeg_file = open(recording_filename,
1900 1909 O_WRONLY| O_APPEND);
1901 DEBUGF("wrl: %x\n", writelen); 1910 if(mpeg_file < 0)
1902 mpeg_file = open(recording_filename, 1911 panicf("rec open: %d", mpeg_file);
1903 O_WRONLY| O_APPEND); 1912
1904 if(mpeg_file < 0) 1913 rc = write(mpeg_file, mp3buf + mp3buf_read,
1905 panicf("rec open: %d", mpeg_file); 1914 writelen);
1906 1915
1907 rc = write(mpeg_file, mp3buf + mp3buf_read, 1916 if(rc < 0)
1908 writelen); 1917 panicf("rec wrt: %d", rc);
1909 1918
1910 if(rc < 0) 1919 rc = close(mpeg_file);
1911 panicf("rec wrt: %d", rc); 1920 if(rc < 0)
1912 1921 panicf("rec cls: %d", rc);
1913 rc = close(mpeg_file); 1922
1914 if(rc < 0) 1923 mpeg_file = -1;
1915 panicf("rec cls: %d", rc); 1924 DEBUGF("rc: %x\n", rc);
1916 1925
1917 mpeg_file = -1; 1926 mp3buf_read += amount_to_save;
1918 DEBUGF("rc: %x\n", rc); 1927 if(mp3buf_read >= mp3buflen)
1919 1928 mp3buf_read = 0;
1920 mp3buf_read += amount_to_save; 1929
1921 if(mp3buf_read >= mp3buflen) 1930 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1922 mp3buf_read = 0;
1923
1924 queue_post(&mpeg_queue, MPEG_SAVE_DATA, 0);
1925 }
1926 else
1927 {
1928 saving = false;
1929 }
1930 } 1931 }
1931 else 1932 else
1932 { 1933 {
1933 /* We have saved all data,
1934 time to stop for real */
1935 if(stop_pending)
1936 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
1937 saving = false; 1934 saving = false;
1938 } 1935 }
1939 break; 1936 }
1940 1937 else
1941 case MPEG_INIT_PLAYBACK: 1938 {
1942 init_playback(); 1939 /* We have saved all data,
1943 init_playback_done = true; 1940 time to stop for real */
1944 break; 1941 if(stop_pending)
1945 } 1942 queue_post(&mpeg_queue, MPEG_STOP_DONE, 0);
1946 /*}*/ 1943 saving = false;
1944 }
1945 break;
1946
1947 case MPEG_INIT_PLAYBACK:
1948 init_playback();
1949 init_playback_done = true;
1950 break;
1951 }
1947 } 1952 }
1948#endif 1953#endif
1949 } 1954 }
@@ -2981,3 +2986,74 @@ void mpeg_init(int volume, int bass, int treble, int balance, int loudness,
2981 dbg_cnt2us(0); 2986 dbg_cnt2us(0);
2982#endif 2987#endif
2983} 2988}
2989
2990int d_1;
2991int d_2;
2992
2993int mpeg_create_xing_header(char *filename, void (*progressfunc)(int))
2994{
2995 struct mp3entry entry;
2996 char xingbuf[417];
2997 int fd;
2998 int rc;
2999 int flen;
3000 int num_frames;
3001 int fpos;
3002
3003 if(progressfunc)
3004 progressfunc(0);
3005
3006 rc = mp3info(&entry, filename);
3007 if(rc < 0)
3008 return rc * 10 - 1;
3009
3010 fd = open(filename, O_RDWR);
3011 if(fd < 0)
3012 return fd * 10 - 2;
3013
3014 flen = lseek(fd, 0, SEEK_END);
3015
3016 d_1 = entry.first_frame_offset;
3017 d_2 = entry.filesize;
3018
3019 if(progressfunc)
3020 progressfunc(0);
3021
3022 num_frames = count_mp3_frames(fd, entry.first_frame_offset,
3023 flen,
3024 progressfunc);
3025
3026 create_xing_header(fd, entry.first_frame_offset,
3027 flen, xingbuf, num_frames, progressfunc);
3028
3029 /* Try to fit the Xing header first in the stream. Replace the existing
3030 Xing header if there is one, else see if there is room between the
3031 ID3 tag and the first MP3 frame. */
3032 if(entry.xing_header_pos)
3033 {
3034 /* Reuse existing Xing header */
3035 fpos = entry.xing_header_pos;
3036 }
3037 else
3038 {
3039 /* Any room between ID3 tag and first MP3 frame? */
3040 if(entry.first_frame_offset - entry.id3v2len > 417)
3041 {
3042 fpos = entry.first_frame_offset - 417;
3043 }
3044 else
3045 {
3046 close(fd);
3047 return -3;
3048 }
3049 }
3050
3051 lseek(fd, fpos, SEEK_SET);
3052 write(fd, xingbuf, 417);
3053 close(fd);
3054
3055 if(progressfunc)
3056 progressfunc(100);
3057
3058 return 0;
3059}