33 audio.cpp
44
55 Created on: Oct 28.2018 */ char audioI2SVers[] =" \
6- Version 3.4.0i " ;
6+ Version 3.4.0j " ;
77/* Updated on: Jul 28.2025
88
99 Author: Wolle (schreibfaul1)
@@ -1877,6 +1877,7 @@ int Audio::read_ID3_Header(uint8_t* data, size_t len) {
18771877 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
18781878 if (m_controlCounter == 6 ) { // Read the value
18791879 m_controlCounter = 5 ; // only read 256 bytes
1880+
18801881 uint8_t textEncodingByte = *(data + 0 ); // ID3v2 Text-Encoding-Byte
18811882 // $00 – ISO-8859-1 (LATIN-1, Identical to ASCII for values smaller than 0x80).
18821883 // $01 – UCS-2 encoded Unicode with BOM (Byte Order Mark), in ID3v2.2 and ID3v2.3.
@@ -1897,6 +1898,7 @@ int Audio::read_ID3_Header(uint8_t* data, size_t len) {
18971898 return 0 ;
18981899 }
18991900
1901+
19001902 if ( // proprietary not standard information
19011903 startsWith (m_ID3Hdr.tag , " PRIV" )) {
19021904 ;// AUDIO_LOG_ERROR("PRIV");
@@ -1905,78 +1907,51 @@ int Audio::read_ID3_Header(uint8_t* data, size_t len) {
19051907
19061908 if (m_ID3Hdr.framesize == 0 ) return 0 ;
19071909
1910+ ps_ptr<char > tmp;
19081911 size_t fs = m_ID3Hdr.framesize ; // fs = size of the frame data field as read from header
19091912 size_t bytesToCopy = fs;
1910-
1911- if (bytesToCopy >= m_ID3Hdr.iBuffSize ) { // <= oder >= hier ist wichtig!
1912- bytesToCopy = m_ID3Hdr.iBuffSize - 1 ; // Sicherstellen, dass ein Null-Terminator passt
1913- }
19141913 size_t textDataLength = 0 ;
1915- if (bytesToCopy > 0 ) { // Nur wenn überhaupt Daten da sind, die wir kürzen können
1916- textDataLength = bytesToCopy - 1 ; // Dies ist die Anzahl der zu kopierenden TEXT-Bytes
1914+
1915+ if (bytesToCopy >= m_ID3Hdr.iBuffSize ) { bytesToCopy = m_ID3Hdr.iBuffSize - 1 ;} // make sure a zero terminator fits
1916+ if (bytesToCopy > 0 ) { textDataLength = bytesToCopy - 1 ;} // Only if there are data that we can shorten
1917+ for (int i = 0 ; i < textDataLength; i++) {
1918+ m_ID3Hdr.iBuff [i] = *(data + i + 1 ); // Skipped the first byte (Encoding)
19171919 }
1918- for (int i = 0 ; i < textDataLength; i++) {
1919- m_ID3Hdr.iBuff [i] = *(data + i + 1 ); // Überspringt das erste Byte (Encoding)
1920+
1921+ if (textEncodingByte == 1 || textEncodingByte == 2 ) { // is UTF-16LE or UTF-16BE
1922+ m_ID3Hdr.iBuff [textDataLength] = 0 ; // UTF-16: set double zero terminator
1923+ m_ID3Hdr.iBuff [textDataLength + 1 ] = 0 ; // second '\0' for UTF-16
1924+ } else {
1925+ m_ID3Hdr.iBuff [textDataLength] = 0 ; // only one '\0' for ISO-8859-1 or UTF-8
19201926 }
1921- m_ID3Hdr. iBuff [textDataLength] = 0 ;
1927+
19221928 m_ID3Hdr.framesize -= fs;
19231929 m_ID3Hdr.remainingHeaderBytes -= fs;
19241930 uint16_t dataLength = fs - 1 ;
19251931
1926- if (textEncodingByte == 0 ){ // latin
1927- latinToUTF8 (m_ID3Hdr.iBuff , false );
1928- showID3Tag (m_ID3Hdr.tag , m_ID3Hdr.iBuff .get ());
1929- }
1930-
1931- if (textEncodingByte == 1 && dataLength > 1 ) { // UTF16 with BOM
1932- int8_t data_start = 0 ;
1933- if (startsWith (m_ID3Hdr.tag , " COMM" )){ // language code
1934- m_ID3Hdr.lang [0 ] = m_ID3Hdr.iBuff [0 ];
1935- m_ID3Hdr.lang [1 ] = m_ID3Hdr.iBuff [1 ];
1936- m_ID3Hdr.lang [2 ] = m_ID3Hdr.iBuff [2 ];
1937- m_ID3Hdr.lang [3 ] = ' \0 ' ;
1938- data_start += 3 ;
1939- // log_w("language code: %s", m_ID3Hdr.lang);
1940- m_ID3Hdr.byteOrderMark = static_cast <unsigned char >(m_ID3Hdr.iBuff [data_start]) == 0xFE && static_cast <unsigned char >(m_ID3Hdr.iBuff [data_start]) == 0xFF ;
1941- data_start += 2 ;
1942- m_ID3Hdr.contentDescriptorTerminator_0 = m_ID3Hdr.iBuff [data_start];
1943- m_ID3Hdr.contentDescriptorTerminator_1 = m_ID3Hdr.iBuff [data_start + 1 ];
1944- m_ID3Hdr.textStringTerminator_0 = m_ID3Hdr.iBuff [data_start + 2 ];
1945- m_ID3Hdr.textStringTerminator_1 = m_ID3Hdr.iBuff [data_start + 3 ];
1946- data_start += 4 ;
1947- }
1948- else {
1949- m_ID3Hdr.byteOrderMark = static_cast <unsigned char >(m_ID3Hdr.iBuff [data_start]) == 0xFE && static_cast <unsigned char >(m_ID3Hdr.iBuff [data_start]) == 0xFF ;
1950- data_start += 2 ;
1951- }
1952-
1953- std::u16string utf16_string;
1954- for (size_t i = data_start; i < dataLength; i += 2 ) {
1955- char16_t wchar;
1956- if (m_ID3Hdr.byteOrderMark ) wchar = (static_cast <unsigned char >(m_ID3Hdr.iBuff [i]) << 8 ) | static_cast <unsigned char >(m_ID3Hdr.iBuff [i + 1 ]);
1957- else wchar = (static_cast <unsigned char >(m_ID3Hdr.iBuff [i + 1 ]) << 8 ) | static_cast <unsigned char >(m_ID3Hdr.iBuff [i]);
1958- utf16_string.push_back (wchar);
1959- }
1960-
1961- std::wstring_convert<std::codecvt_utf8_utf16<char16_t >, char16_t > converter;
1962- showID3Tag (m_ID3Hdr.tag , converter.to_bytes (utf16_string).c_str ());
1932+ if (startsWith (m_ID3Hdr.tag , " COMM" )){ // language code
1933+ m_ID3Hdr.lang [0 ] = m_ID3Hdr.iBuff [0 ];
1934+ m_ID3Hdr.lang [1 ] = m_ID3Hdr.iBuff [1 ];
1935+ m_ID3Hdr.lang [2 ] = m_ID3Hdr.iBuff [2 ];
1936+ m_ID3Hdr.lang [3 ] = ' \0 ' ;
1937+ m_ID3Hdr.iBuff .shift_left (4 );
19631938 }
19641939
1965- if (textEncodingByte == 2 && dataLength > 1 ) { // UTF16BE
1966-
1967- std::u16string utf16_string;
1968- for (size_t i = 0 ; i < dataLength; i += 2 ) {
1969- char16_t wchar = (static_cast <unsigned char >(m_ID3Hdr.iBuff [i]) << 8 ) | static_cast <unsigned char >(m_ID3Hdr.iBuff [i + 1 ]);
1970- utf16_string.push_back (wchar);
1971- }
1940+ char encodingTab [4 ][12 ] = {" ISO-8859-1" , " UTF-16" , " UTF-16BE" , " UTF-8" };
1941+ // AUDIO_LOG_INFO("Tag: %s, Length: %i, Format: %s", m_ID3Hdr.tag, textDataLength, encodingTab[textEncodingByte]);
19721942
1973- std::wstring_convert<std::codecvt_utf8_utf16<char16_t >, char16_t > converter;
1974- showID3Tag (m_ID3Hdr.tag , converter.to_bytes (utf16_string).c_str ());
1943+ if (textEncodingByte == 0 ) { // ISO-8859-1
1944+ tmp.copy_from_iso8859_1 ((const uint8_t *)m_ID3Hdr.iBuff .get (), " tmp" );
1945+ } else if (textEncodingByte == 1 || textEncodingByte == 2 ) { // UTF-16LE oder UTF-16BE
1946+ bool isBigEndian = (textEncodingByte == 2 );
1947+ tmp.copy_from_utf16 ((const uint8_t *)m_ID3Hdr.iBuff .get (), isBigEndian, " tmp" );
1948+ } else if (textEncodingByte == 3 ) { // UTF-8
1949+ // Direkt kopieren, da keine Konvertierung nötig ist
1950+ tmp.copy_from (m_ID3Hdr.iBuff .get ());
19751951 }
19761952
1977- if (textEncodingByte == 3 ) { // utf8
1978- showID3Tag (m_ID3Hdr.tag , m_ID3Hdr.iBuff .get ());
1979- }
1953+ showID3Tag (m_ID3Hdr.tag , tmp.c_get ());
1954+
19801955 return fs;
19811956 }
19821957 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -2009,7 +1984,6 @@ int Audio::read_ID3_Header(uint8_t* data, size_t len) {
20091984 if (!res){AUDIO_LOG_ERROR (" http range request was not successful" ); return 0 ;}
20101985 res = parseHttpRangeHeader ();
20111986 if (!res){AUDIO_LOG_ERROR (" http range response was not successful" ); return 0 ;}
2012- // return 0;
20131987 }
20141988 if (m_dataMode == AUDIO_LOCALFILE){
20151989 uint32_t pos = m_audiofile.position ();
@@ -2031,22 +2005,17 @@ int Audio::read_ID3_Header(uint8_t* data, size_t len) {
20312005 m_ID3Hdr.SYLT .time_stamp_format = syltBuff[4 ];
20322006 m_ID3Hdr.SYLT .content_type = syltBuff[5 ];
20332007 idx = 6 ;
2034- if (m_ID3Hdr.SYLT .text_encoding == 0 || m_ID3Hdr.SYLT .text_encoding == 3 ){ // utf-8
2035- len = content_descriptor.copy_from ((const char *)(syltBuff.get () + idx), " content_descriptor" );
2036- }
2037- else { // utf-16
2038- len = content_descriptor.copy_from_utf16 ((const uint8_t *)(syltBuff.get () + idx), isBigEndian, " content_descriptor" );
2039- }
2008+ if (m_ID3Hdr.SYLT .text_encoding == 0 ) len = 1 + content_descriptor.copy_from_iso8859_1 ((const uint8_t *)(syltBuff.get () + idx), " content_descriptor" ); // iso8859_1
2009+ else if (m_ID3Hdr.SYLT .text_encoding == 3 ) len = 1 + content_descriptor.copy_from ((const char *)(syltBuff.get () + idx), " content_descriptor" ); // utf-8
2010+ else len = 2 + content_descriptor.copy_from_utf16 ((const uint8_t *)(syltBuff.get () + idx), isBigEndian, " content_descriptor" );// utf-16
20402011 if (len > 2 ) AUDIO_INFO (" Lyrics: content_descriptor: %s" , content_descriptor.c_get ());
2012+
20412013 idx += len;
20422014 while (idx < m_ID3Hdr.SYLT .size ) {
2043- // UTF-16LE, UTF-16BE
2044- if (m_ID3Hdr.SYLT .text_encoding == 1 || m_ID3Hdr.SYLT .text_encoding == 2 ) {
2045- idx += tmp.copy_from_utf16 ((const uint8_t *)(syltBuff.get () + idx), isBigEndian, " sylt-text" );
2046- } else {
2047- // ISO-8859-1 / UTF-8
2048- idx += tmp.copy_from ((const char *)syltBuff.get () + idx, " sylt-text" );
2049- }
2015+ if (m_ID3Hdr.SYLT .text_encoding == 0 ) idx += 1 + tmp.copy_from_iso8859_1 ((const uint8_t *)syltBuff.get () + idx, " sylt-text" ); // ISO8859_1
2016+ else if (m_ID3Hdr.SYLT .text_encoding == 3 ) idx += 1 + tmp.copy_from ((const char *)syltBuff.get () + idx, " sylt-text" ); // UTF-8
2017+ else idx += 2 + tmp.copy_from_utf16 ((const uint8_t *)(syltBuff.get () + idx), isBigEndian, " sylt-text" ); // UTF-16LE, UTF-16BE
2018+
20502019 if (tmp.starts_with (" \n " )) tmp.remove_before (1 );
20512020 m_syltLines.push_back (std::move (tmp));
20522021 if (idx + 4 > m_ID3Hdr.SYLT .size ) break ; // no more 4 bytes?
@@ -2061,13 +2030,9 @@ int Audio::read_ID3_Header(uint8_t* data, size_t len) {
20612030 return 0 ;
20622031 }
20632032
2064-
2065-
2066-
2067-
20682033 // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20692034
2070- // --- section V2.2 only , greater Vers above ----
2035+ // --- section V2.2 only , higher Vers above ----
20712036 // see https://mutagen-specs.readthedocs.io/en/latest/id3/id3v2.2.html
20722037 if (m_controlCounter == 10 ) { // frames in V2.2, 3bytes identifier, 3bytes size descriptor
20732038
0 commit comments