From 1971ee6765220872d4ba233557af441481a96882 Mon Sep 17 00:00:00 2001 From: Dave Chapman Date: Thu, 9 Jun 2005 00:23:50 +0000 Subject: [PATCH] Parse the metadata in a FLAC file to populate the "id3" struct (currently only length, samplerate etc) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6627 a1c6a512-1295-4272-9138-f99709370657 --- apps/playback.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/apps/playback.c b/apps/playback.c index 87287e57ab..3a9f229e15 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -572,6 +572,9 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) off_t size; int rc, i; int copy_n; + /* Used by the FLAC metadata parser */ + unsigned long totalsamples; + unsigned char* buf; if (track_count >= MAX_TRACK) return false; @@ -638,6 +641,70 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) tracks[track_widx].taginfo_ready = true; break ; + case AFMT_FLAC: + /* A simple parser to read vital metadata from a FLAC file - length, frequency, bitrate etc. */ + /* This code should either be moved to a seperate file, or discarded in favour of the libFLAC code */ + /* The FLAC stream specification can be found at http://flac.sourceforge.net/format.html#stream */ + + /* Use the trackname part of the id3 structure as a temporary buffer */ + buf=tracks[track_widx].id3.path; + + lseek(fd, 0, SEEK_SET); + + rc = read(fd, buf, 4); + if (rc < 4) { + close(fd); + return false; + } + + if (memcmp(buf,"fLaC",4)!=0) { + logf("%s is not a FLAC file\n",trackname); + close(fd); + return(false); + } + + while (1) { + rc = read(fd, buf, 4); + i = (buf[1]<<16)|(buf[2]<<8)|buf[3]; /* The length of the block */ + + if ((buf[0]&0x7f)==0) { /* 0 is the STREAMINFO block */ + rc = read(fd, buf, i); /* FIXME: Don't trust the value of i */ + if (rc < 0) { + close(fd); + return false; + } + tracks[track_widx].id3.vbr=true; /* All FLAC files are VBR */ + tracks[track_widx].id3.filesize=filesize(fd); + + tracks[track_widx].id3.frequency=(buf[10]<<12)|(buf[11]<<4)|((buf[12]&0xf0)>>4); + + /* NOT NEEDED: bitspersample=(((buf[12]&0x01)<<4)|((buf[13]&0xf0)>>4))+1; */ + + /* totalsamples is a 36-bit field, but we assume <= 32 bits are used */ + totalsamples=(buf[14]<<24)|(buf[15]<<16)|(buf[16]<<8)|buf[17]; + + /* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */ + tracks[track_widx].id3.length=(totalsamples/tracks[track_widx].id3.frequency)*1000; + tracks[track_widx].id3.bitrate=(filesize(fd)*8)/tracks[track_widx].id3.length; + } else if ((buf[0]&0x7f)==4) { /* 4 is the VORBIS_COMMENT block */ + + /* The next i bytes of the file contain the VORBIS COMMENTS - just skip them for now. */ + lseek(fd, i, SEEK_CUR); + + } else { + if (buf[0]&0x80) { /* If we have reached the last metadata block, abort. */ + break; + } else { + lseek(fd, i, SEEK_CUR); /* Skip to next metadata block */ + } + } + } + + lseek(fd, 0, SEEK_SET); + strncpy(tracks[track_widx].id3.path,trackname,sizeof(tracks[track_widx].id3.path)); + tracks[track_widx].taginfo_ready = true; + break; + /* If we don't know how to read the metadata, just store the filename */ default: strncpy(tracks[track_widx].id3.path,trackname,sizeof(tracks[track_widx].id3.path));