mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-10-14 02:27:39 -04:00
wave metadata parser reduces binsize.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25161 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
efeb43b341
commit
2d1937a158
1 changed files with 53 additions and 64 deletions
|
@ -21,8 +21,6 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
@ -51,28 +49,29 @@ enum {
|
||||||
FMT_CHUNK,
|
FMT_CHUNK,
|
||||||
FACT_CHUNK,
|
FACT_CHUNK,
|
||||||
DATA_CHUNK,
|
DATA_CHUNK,
|
||||||
NUM_CHUNKS,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Wave chunk names */
|
/* Wave chunk names */
|
||||||
static const unsigned char *wave_chunknames[NUM_CHUNKS] =
|
#define WAVE_CHUNKNAME_LENGTH 4
|
||||||
{
|
#define WAVE_CHUNKSIZE_LENGTH 4
|
||||||
[RIFF_CHUNK] = "RIFF",
|
|
||||||
[WAVE_CHUNK] = "WAVE",
|
static const unsigned char *wave_chunklist = "RIFF"
|
||||||
[FMT_CHUNK] = "fmt ",
|
"WAVE"
|
||||||
[FACT_CHUNK] = "fact",
|
"fmt "
|
||||||
[DATA_CHUNK] = "data",
|
"fact"
|
||||||
};
|
"data";
|
||||||
|
|
||||||
/* Wave64 GUIDs */
|
/* Wave64 GUIDs */
|
||||||
static const unsigned char *wave64_chunknames[NUM_CHUNKS] =
|
#define WAVE64_CHUNKNAME_LENGTH 16
|
||||||
{
|
#define WAVE64_CHUNKSIZE_LENGTH 8
|
||||||
[RIFF_CHUNK] = "riff\x2e\x91\xcf\x11\xa5\xd6\x28\xdb\x04\xc1\x00\x00",
|
|
||||||
[WAVE_CHUNK] = "wave\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a",
|
static const unsigned char *wave64_chunklist
|
||||||
[FMT_CHUNK] = "fmt \xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a",
|
= "riff\x2e\x91\xcf\x11\xa5\xd6\x28\xdb\x04\xc1\x00\x00"
|
||||||
[FACT_CHUNK] = "fact\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a",
|
"wave\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a"
|
||||||
[DATA_CHUNK] = "data\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a",
|
"fmt \xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a"
|
||||||
};
|
"fact\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a"
|
||||||
|
"data\xf3\xac\xd3\x11\x8c\xd1\x00\xc0\x4f\x8e\xdb\x8a";
|
||||||
|
|
||||||
|
|
||||||
/* support formats */
|
/* support formats */
|
||||||
enum
|
enum
|
||||||
|
@ -113,45 +112,35 @@ static void set_totalsamples(struct wave_fmt *fmt, struct mp3entry* id3)
|
||||||
case WAVE_FORMAT_MULAW:
|
case WAVE_FORMAT_MULAW:
|
||||||
case IBM_FORMAT_ALAW:
|
case IBM_FORMAT_ALAW:
|
||||||
case IBM_FORMAT_MULAW:
|
case IBM_FORMAT_MULAW:
|
||||||
if (fmt->bitspersample != 0 && fmt->channels != 0)
|
fmt->blockalign = fmt->bitspersample * fmt->channels >> 3;
|
||||||
fmt->totalsamples = fmt->numbytes / ((fmt->bitspersample >> 3) * fmt->channels);
|
fmt->samplesperblock = 1;
|
||||||
break;
|
|
||||||
case WAVE_FORMAT_ADPCM:
|
|
||||||
case WAVE_FORMAT_DVI_ADPCM:
|
|
||||||
case WAVE_FORMAT_XBOX_ADPCM:
|
|
||||||
if (fmt->blockalign != 0)
|
|
||||||
fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
|
|
||||||
break;
|
break;
|
||||||
case WAVE_FORMAT_YAMAHA_ADPCM:
|
case WAVE_FORMAT_YAMAHA_ADPCM:
|
||||||
if (fmt->blockalign != 0 && fmt->channels != 0)
|
if (id3->channels != 0)
|
||||||
{
|
{
|
||||||
if (fmt->samplesperblock == 0)
|
fmt->samplesperblock =
|
||||||
{
|
(fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels)?
|
||||||
if (fmt->blockalign == ((id3->frequency / 60) + 4) * fmt->channels)
|
id3->frequency / 30 : (fmt->blockalign << 1) / fmt->channels;
|
||||||
fmt->samplesperblock = id3->frequency / 30;
|
|
||||||
else
|
|
||||||
fmt->samplesperblock = (fmt->blockalign << 1) / fmt->channels;
|
|
||||||
}
|
|
||||||
fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
|
case WAVE_FORMAT_DIALOGIC_OKI_ADPCM:
|
||||||
fmt->totalsamples = fmt->numbytes << 1;
|
fmt->blockalign = 1;
|
||||||
|
fmt->samplesperblock = 2;
|
||||||
break;
|
break;
|
||||||
case WAVE_FORMAT_SWF_ADPCM:
|
case WAVE_FORMAT_SWF_ADPCM:
|
||||||
if (fmt->blockalign != 0 && fmt->bitspersample != 0 && fmt->channels != 0)
|
if (fmt->bitspersample != 0 && id3->channels != 0)
|
||||||
{
|
{
|
||||||
if (fmt->samplesperblock == 0)
|
fmt->samplesperblock
|
||||||
fmt->samplesperblock = (((fmt->blockalign << 3) - 2) / fmt->channels - 22)
|
= (((fmt->blockalign << 3) - 2) / fmt->channels - 22)
|
||||||
/ fmt->bitspersample;
|
/ fmt->bitspersample + 1;
|
||||||
|
|
||||||
fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fmt->totalsamples = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fmt->blockalign != 0)
|
||||||
|
fmt->totalsamples = (fmt->numbytes / fmt->blockalign) * fmt->samplesperblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt *fmt,
|
static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt *fmt,
|
||||||
|
@ -208,15 +197,16 @@ static void parse_riff_format(unsigned char* buf, int fmtsize, struct wave_fmt *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chunknames, bool is_64)
|
static bool read_header(int fd, struct mp3entry* id3, const unsigned char *chunknames,
|
||||||
|
bool is_64)
|
||||||
{
|
{
|
||||||
/* Use the temporary buffer */
|
/* Use the temporary buffer */
|
||||||
unsigned char* buf = (unsigned char *)id3->path;
|
unsigned char* buf = (unsigned char *)id3->path;
|
||||||
|
|
||||||
struct wave_fmt fmt;
|
struct wave_fmt fmt;
|
||||||
|
|
||||||
unsigned int namelen = (is_64)? 16 : 4;
|
unsigned int namelen = (is_64)? WAVE64_CHUNKNAME_LENGTH : WAVE_CHUNKNAME_LENGTH;
|
||||||
unsigned int sizelen = (is_64)? 8 : 4;
|
unsigned int sizelen = (is_64)? WAVE64_CHUNKSIZE_LENGTH : WAVE_CHUNKSIZE_LENGTH;
|
||||||
unsigned int len = namelen + sizelen;
|
unsigned int len = namelen + sizelen;
|
||||||
uint64_t chunksize;
|
uint64_t chunksize;
|
||||||
uint64_t offset = len + namelen;
|
uint64_t offset = len + namelen;
|
||||||
|
@ -228,8 +218,8 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun
|
||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
read(fd, buf, offset);
|
read(fd, buf, offset);
|
||||||
|
|
||||||
if ((memcmp(buf, chunknames[RIFF_CHUNK], namelen) != 0) ||
|
if ((memcmp(buf, chunknames + RIFF_CHUNK * namelen, namelen) != 0) ||
|
||||||
(memcmp(buf + len, chunknames[WAVE_CHUNK], namelen) != 0))
|
(memcmp(buf + len, chunknames + WAVE_CHUNK * namelen, namelen) != 0))
|
||||||
{
|
{
|
||||||
DEBUGF("metadata error: missing riff header.\n");
|
DEBUGF("metadata error: missing riff header.\n");
|
||||||
return false;
|
return false;
|
||||||
|
@ -251,7 +241,7 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun
|
||||||
chunksize = (is_64) ? get_uint64_le(buf + namelen) - len :
|
chunksize = (is_64) ? get_uint64_le(buf + namelen) - len :
|
||||||
get_long_le(buf + namelen);
|
get_long_le(buf + namelen);
|
||||||
|
|
||||||
if (memcmp(buf, chunknames[DATA_CHUNK], namelen) == 0)
|
if (memcmp(buf, chunknames + DATA_CHUNK * namelen, namelen) == 0)
|
||||||
{
|
{
|
||||||
DEBUGF("find 'data' chunk\n");
|
DEBUGF("find 'data' chunk\n");
|
||||||
fmt.numbytes = chunksize;
|
fmt.numbytes = chunksize;
|
||||||
|
@ -265,7 +255,7 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun
|
||||||
offset += chunksize;
|
offset += chunksize;
|
||||||
|
|
||||||
read_data = 0;
|
read_data = 0;
|
||||||
if (memcmp(buf, chunknames[FMT_CHUNK], namelen) == 0)
|
if (memcmp(buf, chunknames + FMT_CHUNK * namelen, namelen) == 0)
|
||||||
{
|
{
|
||||||
DEBUGF("find 'fmt ' chunk\n");
|
DEBUGF("find 'fmt ' chunk\n");
|
||||||
|
|
||||||
|
@ -281,7 +271,7 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun
|
||||||
read(fd, buf, read_data);
|
read(fd, buf, read_data);
|
||||||
parse_riff_format(buf, read_data, &fmt, id3);
|
parse_riff_format(buf, read_data, &fmt, id3);
|
||||||
}
|
}
|
||||||
else if (memcmp(buf, chunknames[FACT_CHUNK], namelen) == 0)
|
else if (memcmp(buf, chunknames + FACT_CHUNK * namelen, namelen) == 0)
|
||||||
{
|
{
|
||||||
DEBUGF("find 'fact' chunk\n");
|
DEBUGF("find 'fact' chunk\n");
|
||||||
|
|
||||||
|
@ -301,20 +291,19 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun
|
||||||
if (fmt.totalsamples == 0)
|
if (fmt.totalsamples == 0)
|
||||||
set_totalsamples(&fmt, id3);
|
set_totalsamples(&fmt, id3);
|
||||||
|
|
||||||
|
if (id3->frequency == 0 || id3->bitrate == 0)
|
||||||
|
{
|
||||||
|
DEBUGF("metadata error: frequency or bitrate is 0\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
id3->vbr = false; /* All Wave/Wave64 files are CBR */
|
id3->vbr = false; /* All Wave/Wave64 files are CBR */
|
||||||
id3->filesize = filesize(fd);
|
id3->filesize = filesize(fd);
|
||||||
|
|
||||||
/* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */
|
/* Calculate track length (in ms) and estimate the bitrate (in kbit/s) */
|
||||||
if(fmt.formattag != WAVE_FORMAT_ATRAC3)
|
id3->length = (fmt.formattag != WAVE_FORMAT_ATRAC3)?
|
||||||
{
|
(uint64_t)fmt.totalsamples * 1000 / id3->frequency :
|
||||||
if (id3->frequency != 0)
|
((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate;
|
||||||
id3->length = ((int64_t) fmt.totalsamples * 1000) / id3->frequency;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (id3->bitrate != 0)
|
|
||||||
id3->length = ((id3->filesize - id3->first_frame_offset) * 8) / id3->bitrate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* output header/id3 info (for debug) */
|
/* output header/id3 info (for debug) */
|
||||||
DEBUGF("%s header info ----\n", (is_64)? "wave64" : "wave");
|
DEBUGF("%s header info ----\n", (is_64)? "wave64" : "wave");
|
||||||
|
@ -335,10 +324,10 @@ static bool read_header(int fd, struct mp3entry* id3, const unsigned char **chun
|
||||||
|
|
||||||
bool get_wave_metadata(int fd, struct mp3entry* id3)
|
bool get_wave_metadata(int fd, struct mp3entry* id3)
|
||||||
{
|
{
|
||||||
return read_header(fd, id3, (const unsigned char **)&wave_chunknames, false);
|
return read_header(fd, id3, wave_chunklist, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool get_wave64_metadata(int fd, struct mp3entry* id3)
|
bool get_wave64_metadata(int fd, struct mp3entry* id3)
|
||||||
{
|
{
|
||||||
return read_header(fd, id3, (const unsigned char **)&wave64_chunknames, true);
|
return read_header(fd, id3, wave64_chunklist, true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue