Skip to content

Commit

Permalink
Improve MP3 detection slightly more.
Browse files Browse the repository at this point in the history
Looking too much result in increase of false-positive and vice-versa. So only look first 128 bytes of the file (after the ID3 tags). Also reject known audio file signature such as WAV, Ogg (Theora/Vorbis), and FLAC.

Fixes #1939
  • Loading branch information
MikuAuahDark committed Jun 6, 2023
1 parent 8efcf27 commit d28b307
Showing 1 changed file with 16 additions and 18 deletions.
34 changes: 16 additions & 18 deletions src/modules/sound/lullaby/MP3Decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,24 +30,14 @@ namespace sound
namespace lullaby
{

// Copied from dr_mp3 function drmp3_hdr_valid()
static bool isMP3HeaderValid(const uint8 *h)
{
return
// Sync bits
h[0] == 0xff &&
((h[1] & 0xF0) == 0xf0 || (h[1] & 0xFE) == 0xe2) &&
// Check layer
(DRMP3_HDR_GET_LAYER(h) != 0) &&
// Check bitrate
(DRMP3_HDR_GET_BITRATE(h) != 15) &&
// Check sample rate
(DRMP3_HDR_GET_SAMPLE_RATE(h) != 3);
}

// dr_mp3 looks too far, but it can lead to false-positive. dr_mp3 also doesn't recognize ID3.
// Implement our own "MP3 detection" heuristics that also help dr_mp3 skip ID3 tags.
static int64 findFirstValidHeader(Stream* stream)
{
constexpr size_t LOOKUP_SIZE = 16384;
// Tweaking this variable has trade-off between false-positive and false-negative. Lesser value
// means lesser false-positive and false-negative. Larger value means more false-positive AND
// false-negative.
constexpr size_t LOOKUP_SIZE = 128;

std::vector<uint8> data(LOOKUP_SIZE);
uint8 header[10];
Expand All @@ -58,6 +48,14 @@ static int64 findFirstValidHeader(Stream* stream)
if (stream->read(header, 10) < 10)
return -1;

// Test for known audio formats which are definitely not MP3.
if (memcmp(header, "RIFF", 4) == 0)
return -1;
if (memcmp(header, "OggS", 4) == 0)
return -1;
if (memcmp(header, "fLaC", 4) == 0)
return -1;

if (memcmp(header, "TAG", 3) == 0)
{
// ID3v1 tag is always 128 bytes long
Expand Down Expand Up @@ -93,14 +91,14 @@ static int64 findFirstValidHeader(Stream* stream)
// Look for mp3 data
for (int i = 0; i < buffer - 4; i++, offset++)
{
if (isMP3HeaderValid(dataPtr++))
if (drmp3_hdr_valid(dataPtr++))
{
stream->seek(offset, Stream::SEEKORIGIN_BEGIN);
return offset;
}
}

// No valid MP3 frame found in first 16KB data
// No valid MP3 frame found in first few bytes of the data.
return -1;
}

Expand Down

0 comments on commit d28b307

Please sign in to comment.