summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/playback.c67
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));