33 * libhelix_HMP3DECODER
44 *
55 * Created on: 26.10.2018
6- * Updated on: 07 .07.2025
6+ * Updated on: 09 .07.2025
77 */
88#include " mp3_decoder.h"
99/* clip to range [-2^n, 2^n - 1] */
@@ -1185,7 +1185,43 @@ int32_t MP3FindSyncWord(uint8_t *buf, int32_t nBytes) {
11851185 // auto extract_bits = [&](uint8_t byte, uint8_t start_bit, uint8_t num_bits) {
11861186 // return (byte >> (8 - start_bit - num_bits)) & ((1 << num_bits) - 1);
11871187 // };
1188+ const uint8_t SYNCWORDH = 0xff ;
1189+ const uint8_t SYNCWORDL = 0xe0 ;
1190+
1191+ typedef struct {
1192+ uint8_t mpeg_version; // 0=MPEG2.5, 1=reserved, 2=MPEG2, 3=MPEG1
1193+ uint8_t layer; // 0=reserved, 1=Layer III, 2=Layer II, 3=Layer I
1194+ bool crc_protected;
1195+ uint8_t bitrate_idx;
1196+ uint8_t sample_rate_idx;
1197+ bool padding;
1198+ uint8_t channel_mode;
1199+ uint32_t frame_length; // In Bytes
1200+ uint16_t sample_rate_hz; // Die tatsächliche Abtastrate in Hz
1201+ uint16_t bitrate_kbps; // Die tatsächliche Bitrate in kbps
1202+ uint16_t samples_per_frame;
1203+ } Mp3FrameHeader;
1204+
1205+ // SamplingFrequenz-Lookup tables(Beispiel für MPEG1, MPEG2, MPEG2.5)
1206+ const uint16_t sampling_rates[3 ][4 ] = {
1207+ {44100 , 48000 , 32000 , 0 }, // MPEG1
1208+ {22050 , 24000 , 16000 , 0 }, // MPEG2
1209+ {11025 , 12000 , 8000 , 0 } // MPEG2.5
1210+ };
1211+
1212+ typedef enum { /* map to 0,1,2 to make table indexing easier */
1213+ MPEG1 = 0 ,
1214+ MPEG2 = 1 ,
1215+ MPEG25 = 2
1216+ } MPEGVersion_t;
1217+
1218+ const uint16_t mpeg1_layer1_bitrates[16 ] = {
1219+ 0 , 32 , 64 , 96 , 128 , 160 , 192 , 224 , 256 , 288 , 320 , 352 , 384 , 416 , 448 , 0
1220+ };
11881221
1222+ const uint16_t mpeg1_layer3_bitrates[16 ] = { // Bitraten-Lookup tables (example for MPEG1 Layer III)
1223+ 0 , 32 , 40 , 48 , 56 , 64 , 80 , 96 , 112 , 128 , 160 , 192 , 224 , 256 , 320 , 0 // Attention: These tables must be complete and correct!
1224+ };
11891225 // Define bitrate tables for MPEG1 Layer II and MPEG2/2.5 Layer II
11901226 // These tables are examples and need to be complete based on the MPEG standard
11911227 const uint16_t mpeg1_layer2_bitrates[] = {
@@ -1228,9 +1264,9 @@ int32_t MP3FindSyncWord(uint8_t *buf, int32_t nBytes) {
12281264 return false ;
12291265 }
12301266 // Modified part: Support for Layer II and Layer III
1231- if (header_info->layer != 1 && header_info->layer != 2 ) { // Allow Layer II (2) and Layer III (1)
1267+ if (header_info->layer != 1 && header_info->layer != 2 && header_info-> layer != 3 ) { // Allow Layer I (3) Layer II (2) and Layer III (1)
12321268 printf (" \n " ); for (int i = 0 ; i<10 ; i++) printf (" 0x%02x " , header_data[i]); printf (" \n " ); // Use header_data instead of buf
1233- log_d (" Not Layer II or III\n " );
1269+ log_d (" Not Layer I or II or III\n " );
12341270 return false ;
12351271 }
12361272
@@ -1261,13 +1297,17 @@ int32_t MP3FindSyncWord(uint8_t *buf, int32_t nBytes) {
12611297 bitrate_kbps = mpeg1_layer3_bitrates[header_info->bitrate_idx ];
12621298 } else if (header_info->layer == 2 ) { // Layer II
12631299 bitrate_kbps = mpeg1_layer2_bitrates[header_info->bitrate_idx ];
1300+ } else if (header_info->layer == 3 ) { // Layer I
1301+ bitrate_kbps = mpeg1_layer1_bitrates[header_info->bitrate_idx ];
12641302 }
12651303 } else if (header_info->mpeg_version == 2 || header_info->mpeg_version == 0 ) { // MPEG 2 or MPEG 2.5
12661304 if (header_info->layer == 1 ) { // Layer III
1267- bitrate_kbps = mpeg2_layer3_bitrates[header_info->bitrate_idx ]; // Assuming mpeg2_layer3_bitrates exists
1305+ bitrate_kbps = mpeg2_layer3_bitrates[header_info->bitrate_idx ];
12681306 } else if (header_info->layer == 2 ) { // Layer II
12691307 bitrate_kbps = mpeg2_layer2_bitrates[header_info->bitrate_idx ];
12701308 }
1309+ // If you also want to support MPEG 2/2.5 Layer I, you'd add another else if here
1310+ // e.g., else if (header_info->layer == 3) { bitrate_kbps = mpeg2_layer1_bitrates[header_info->bitrate_idx]; }
12711311 }
12721312
12731313 if (bitrate_kbps == 0 || sample_rate_hz == 0 ) {
@@ -1292,9 +1332,18 @@ int32_t MP3FindSyncWord(uint8_t *buf, int32_t nBytes) {
12921332 } else if (header_info->mpeg_version == 2 || header_info->mpeg_version == 0 ) { // MPEG 2/2.5 Layer II
12931333 header_info->frame_length = (144 * bitrate_kbps * 1000 ) / sample_rate_hz;
12941334 }
1335+ } else if (header_info->layer == 3 ) { // Layer I
1336+ // For Layer I, the formula is (Bitrate * 12 / SampleRate) + Padding (in Bytes)
1337+ // Note: Bitrate is in kbps, so multiply by 1000 to get bps
1338+ if (header_info->mpeg_version == 3 ) { // MPEG 1 Layer I
1339+ header_info->frame_length = (bitrate_kbps * 1000 / 8 * 12 ) / sample_rate_hz; // Correct
1340+ } else if (header_info->mpeg_version == 2 || header_info->mpeg_version == 0 ) { // MPEG 2/2.5 Layer I (if supported)
1341+ // You'd add the specific calculation for MPEG2/2.5 Layer I here
1342+ // For MPEG 2/2.5 Layer I, samples per frame is 576, so the constant is 6
1343+ header_info->frame_length = (bitrate_kbps * 1000 / 8 * 6 ) / sample_rate_hz; // Hypothetical, verify constant
1344+ }
12951345 }
12961346
1297-
12981347 if (header_info->padding ) {
12991348 header_info->frame_length += 1 ; // Füge 1 Byte für Padding hinzu
13001349 }
@@ -1303,7 +1352,34 @@ int32_t MP3FindSyncWord(uint8_t *buf, int32_t nBytes) {
13031352 log_d (" Calculated frame length is zero\n " );
13041353 return false ;
13051354 }
1306-
1355+ header_info->sample_rate_hz = sample_rate_hz;
1356+ header_info->bitrate_kbps = bitrate_kbps;
1357+
1358+ // Determine samples_per_frame based on the version and layer
1359+ if (header_info->mpeg_version == 3 ) { // MPEG-1
1360+ if (header_info->layer == 1 || header_info->layer == 2 ) { // Layer III oder Layer II
1361+ header_info->samples_per_frame = 1152 ;
1362+ } else if (header_info->layer == 3 ) { // Layer I
1363+ header_info->samples_per_frame = 384 ;
1364+ } else {
1365+ header_info->samples_per_frame = 0 ; // Should be caught by previous checks
1366+ return false ;
1367+ }
1368+ } else if (header_info->mpeg_version == 2 || header_info->mpeg_version == 0 ) { // MPEG-2 oder MPEG-2.5
1369+ if (header_info->layer == 1 ) { // Layer III
1370+ header_info->samples_per_frame = 576 ;
1371+ } else if (header_info->layer == 2 ) { // Layer II
1372+ header_info->samples_per_frame = 1152 ;
1373+ } else if (header_info->layer == 3 ) { // Layer I
1374+ header_info->samples_per_frame = 576 ; // Correct for MPEG-2/2.5 Layer I
1375+ } else {
1376+ header_info->samples_per_frame = 0 ; // Should be caught by previous checks
1377+ return false ;
1378+ }
1379+ } else { // header_info->mpeg_version == 1 (Reserved)
1380+ header_info->samples_per_frame = 0 ;
1381+ return false ;
1382+ }
13071383 return true ; // Header ist gültig
13081384 };
13091385
@@ -1313,8 +1389,8 @@ int32_t MP3FindSyncWord(uint8_t *buf, int32_t nBytes) {
13131389 auto findSync = [&](uint8_t * search_buf, uint16_t offset, uint16_t len) {
13141390 for (int32_t i = 0 ; i < len - 1 ; i++) {
13151391 // Prüfe auf die 11 oder 12 Sync-Bits
1316- if ((search_buf[i + offset] == m_SYNCWORDH ) &&
1317- ((search_buf[i + offset + 1 ] & m_SYNCWORDL ) == m_SYNCWORDL )) {
1392+ if ((search_buf[i + offset] == SYNCWORDH ) &&
1393+ ((search_buf[i + offset + 1 ] & SYNCWORDL ) == SYNCWORDL )) {
13181394 return i;
13191395 }
13201396 }
@@ -1345,11 +1421,23 @@ int32_t MP3FindSyncWord(uint8_t *buf, int32_t nBytes) {
13451421 if (current_pos + header.frame_length + mp3FHsize <= current_pos + nBytes) {
13461422 // Check whether there is a syncword at the expected next frame start and a valid header is (optional but very robust)
13471423 Mp3FrameHeader next_header;
1348- if (((buf[current_pos + header.frame_length ] == m_SYNCWORDH) &&
1349- ((buf[current_pos + header.frame_length + 1 ] & m_SYNCWORDL) == m_SYNCWORDL)) &&
1350- parseMp3Header (&buf[current_pos + header.frame_length ], &next_header)
1351- ) {
1424+ if (((buf[current_pos + header.frame_length ] == SYNCWORDH) && ((buf[current_pos + header.frame_length + 1 ] & SYNCWORDL) == SYNCWORDL)) &&
1425+ parseMp3Header (&buf[current_pos + header.frame_length ], &next_header)) {
13521426 log_d (" Found reliable MP3 frame at pos: %d, length: %lu\n " , current_pos, header.frame_length );
1427+
1428+ // s_samplerate = header.sample_rate_hz; // (angenommen in der Struktur vorhanden)
1429+ // s_bitRate = header.bitrate_kbps; // (angenommen in der Struktur vorhanden)
1430+ // s_mpeg_version = header.mpeg_version;
1431+ // s_layer = header.layer;
1432+ // s_channel_mode = header.channel_mode;
1433+ // s_samples_per_frame = header.samples_per_frame;
1434+
1435+ // // Für s_channels (1 für Mono, 2 für Stereo)
1436+ // if (header.channel_mode == 0b11) { // 0b11 ist Mono
1437+ // s_channels = 1;
1438+ // } else { // Alle anderen Modi (Stereo, Joint Stereo, Dual Channel) sind 2 Kanäle
1439+ // s_channels = 2;
1440+ // }
13531441 return current_pos;
13541442 } else {
13551443 log_d (" Header valid, but next frame does not validate. False positive. Moving on.\n " );
@@ -1523,7 +1611,7 @@ void MP3ClearBadFrame(int16_t *outbuf) {
15231611 * Notes: switching useSize on and off between frames in the same stream
15241612 * is not supported (bit reservoir is not maintained if useSize on)
15251613 **********************************************************************************************************************/
1526- int32_t MP3Decode ( uint8_t *inbuf, int32_t *bytesLeft, int16_t *outbuf, int32_t useSize ){
1614+ int32_t MP3Decode ( uint8_t *inbuf, int32_t *bytesLeft, int16_t *outbuf){
15271615
15281616 // int pos = MP3FindSyncWord(inbuf, *bytesLeft);
15291617 // if(pos > 0){*bytesLeft -= pos; MP3_INFO("skip %i bytes", pos); return MP3_NONE; }
@@ -1576,21 +1664,21 @@ int32_t MP3Decode( uint8_t *inbuf, int32_t *bytesLeft, int16_t *outbuf, int32_t
15761664 * - calling function should set mainDataBegin to 0, and tell us exactly how large this
15771665 * frame is (in bytesLeft)
15781666 */
1579- if (useSize) {
1580- m_MP3DecInfo->nSlots = *bytesLeft;
1581- if (m_MP3DecInfo->mainDataBegin != 0 || m_MP3DecInfo->nSlots <= 0 ) {
1582- /* error - non self-contained frame, or missing frame (size <= 0), could do loss concealment here */
1583- MP3ClearBadFrame (outbuf);
1584- MP3_ERROR (" MP3, invalid frameheader" );
1585- return MP3_ERR;
1586- }
1587-
1588- /* can operate in-place on reformatted frames */
1589- m_MP3DecInfo->mainDataBytes = m_MP3DecInfo->nSlots ;
1590- mainPtr = inbuf;
1591- inbuf += m_MP3DecInfo->nSlots ;
1592- *bytesLeft -= (m_MP3DecInfo->nSlots );
1593- } else {
1667+ // if (useSize) {
1668+ // m_MP3DecInfo->nSlots = *bytesLeft;
1669+ // if (m_MP3DecInfo->mainDataBegin != 0 || m_MP3DecInfo->nSlots <= 0) {
1670+ // /* error - non self-contained frame, or missing frame (size <= 0), could do loss concealment here */
1671+ // MP3ClearBadFrame(outbuf);
1672+ // MP3_ERROR("MP3, invalid frameheader");
1673+ // return MP3_ERR;
1674+ // }
1675+
1676+ // /* can operate in-place on reformatted frames */
1677+ // m_MP3DecInfo->mainDataBytes = m_MP3DecInfo->nSlots;
1678+ // mainPtr = inbuf;
1679+ // inbuf += m_MP3DecInfo->nSlots;
1680+ // *bytesLeft -= (m_MP3DecInfo->nSlots);
1681+ // } else {
15941682 /* out of data - assume last or truncated frame */
15951683 if (m_MP3DecInfo->nSlots > *bytesLeft) {
15961684 MP3ClearBadFrame (outbuf);
@@ -1625,7 +1713,7 @@ int32_t MP3Decode( uint8_t *inbuf, int32_t *bytesLeft, int16_t *outbuf, int32_t
16251713 MP3_ERROR (" MP3, maindata underflow" );
16261714 return MP3_ERR;
16271715 }
1628- }
1716+ // }
16291717 bitOffset = 0 ;
16301718 mainBits = m_MP3DecInfo->mainDataBytes * 8 ;
16311719
0 commit comments