diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/playback.c | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/apps/playback.c b/apps/playback.c index b81ee986cb..0bd0c27c03 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -605,9 +605,10 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
605 | off_t size; | 605 | off_t size; |
606 | int rc, i; | 606 | int rc, i; |
607 | int copy_n; | 607 | int copy_n; |
608 | /* Used by the FLAC metadata parser */ | 608 | /* Used by the metadata parsers */ |
609 | unsigned long totalsamples,bytespersample,channels,bitspersample,numbytes; | 609 | unsigned long totalsamples,bytespersample,channels,bitspersample,numbytes; |
610 | unsigned char* buf; | 610 | unsigned char* buf; |
611 | int j,eof; | ||
611 | 612 | ||
612 | if (track_count >= MAX_TRACK) | 613 | if (track_count >= MAX_TRACK) |
613 | return false; | 614 | return false; |
@@ -803,6 +804,18 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
803 | case AFMT_OGG_VORBIS: | 804 | case AFMT_OGG_VORBIS: |
804 | /* A simple parser to read vital metadata from an Ogg Vorbis file */ | 805 | /* A simple parser to read vital metadata from an Ogg Vorbis file */ |
805 | 806 | ||
807 | /* An Ogg File is split into pages, each starting with the string | ||
808 | "OggS". Each page has a timestamp (in PCM samples) referred to as | ||
809 | the "granule position". | ||
810 | |||
811 | An Ogg Vorbis has the following structure: | ||
812 | 1) Identification header (containing samplerate, numchannels, etc) | ||
813 | 2) Comment header - containing the Vorbis Comments | ||
814 | 3) Setup header - containing codec setup information | ||
815 | 4) Many audio packets... | ||
816 | |||
817 | */ | ||
818 | |||
806 | /* Use the trackname part of the id3 structure as a temporary buffer */ | 819 | /* Use the trackname part of the id3 structure as a temporary buffer */ |
807 | buf=tracks[track_widx].id3.path; | 820 | buf=tracks[track_widx].id3.path; |
808 | 821 | ||
@@ -825,18 +838,48 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
825 | tracks[track_widx].id3.frequency=buf[40]|(buf[41]<<8)|(buf[42]<<16)|(buf[43]<<24); | 838 | tracks[track_widx].id3.frequency=buf[40]|(buf[41]<<8)|(buf[42]<<16)|(buf[43]<<24); |
826 | channels=buf[39]; | 839 | channels=buf[39]; |
827 | 840 | ||
828 | /* We should calculate an accurate average bps, but for now, just take | 841 | /* We now need to search for the last page in the file - identified by |
829 | the "nominal bitrate" from the Ogg header */ | 842 | by ('O','g','g','S',0) and retrieve totalsamples */ |
830 | tracks[track_widx].id3.bitrate=(buf[48]|(buf[49]<<8)|(buf[50]<<16)|(buf[51]<<24))/1000; | 843 | |
831 | tracks[track_widx].id3.vbr=true; | 844 | lseek(fd, -32*1024, SEEK_END); |
832 | 845 | eof=0; | |
833 | if (tracks[track_widx].id3.bitrate!=0) { | 846 | j=0; /* The number of bytes currently in buffer */ |
834 | /* A _really_ stupid and inaccurate calculation, but the best | 847 | i=0; |
835 | I can do at the moment. */ | 848 | totalsamples=0; |
836 | tracks[track_widx].id3.length=(tracks[track_widx].filesize)/(tracks[track_widx].id3.bitrate/8); | 849 | while (!eof) { |
837 | } else { | 850 | rc = read(fd, &buf[j], MAX_PATH-j); |
838 | tracks[track_widx].id3.length=0; | 851 | if (rc <= 0) { |
852 | eof=1; | ||
853 | } else { | ||
854 | j+=rc; | ||
855 | } | ||
856 | /* Inefficient (but simple) search */ | ||
857 | i=0; | ||
858 | while (i < (j-5)) { | ||
859 | if (memcmp(&buf[i],"OggS",5)==0) { | ||
860 | if (i < (j-10)) { | ||
861 | totalsamples=(buf[i+6])|(buf[i+7]<<8)|(buf[i+8]<<16)|(buf[i+9]<<24); | ||
862 | j=0; /* We can discard the rest of the buffer */ | ||
863 | } else { | ||
864 | break; | ||
865 | } | ||
866 | } else { | ||
867 | i++; | ||
868 | } | ||
869 | } | ||
870 | if (i < (j-5)) { | ||
871 | /* Move OggS to start of buffer */ | ||
872 | while(i>0) buf[i--]=buf[j--]; | ||
873 | } else { | ||
874 | j=0; | ||
875 | } | ||
839 | } | 876 | } |
877 | |||
878 | tracks[track_widx].id3.length=(totalsamples/tracks[track_widx].id3.frequency)*1000; | ||
879 | |||
880 | /* The following calculation should use datasize, not filesize (i.e. exclude comments etc) */ | ||
881 | tracks[track_widx].id3.bitrate=(filesize(fd)*8)/tracks[track_widx].id3.length; | ||
882 | tracks[track_widx].id3.vbr=true; | ||
840 | 883 | ||
841 | lseek(fd, 0, SEEK_SET); | 884 | lseek(fd, 0, SEEK_SET); |
842 | strncpy(tracks[track_widx].id3.path,trackname,sizeof(tracks[track_widx].id3.path)); | 885 | strncpy(tracks[track_widx].id3.path,trackname,sizeof(tracks[track_widx].id3.path)); |