33 *
44 * Created on: Oct 26.2018
55 *
6- * Version 2.0.6s
7- * Updated on: Nov 21 .2022
6+ * Version 2.0.7
7+ * Updated on: Nov 22 .2022
88 * Author: Wolle (schreibfaul1)
99 *
1010 */
@@ -2853,23 +2853,18 @@ void Audio::processLocalFile() {
28532853 const uint32_t maxFrameSize = InBuff.getMaxBlockSize (); // every mp3/aac frame is not bigger
28542854 static bool f_stream;
28552855 static bool f_fileDataComplete;
2856- static uint32_t pos_stsz;
28572856 static uint32_t byteCounter; // count received data
2858- static uint32_t stszEntries = 0 ;
28592857 uint32_t availableBytes = 0 ;
28602858
28612859 if (m_f_firstCall) { // runs only one time per connection, prepare for start
28622860 m_f_firstCall = false ;
28632861 f_stream = false ;
28642862 f_fileDataComplete = false ;
28652863 byteCounter = 0 ;
2866- pos_stsz = 0 ;
2867- if (m_codec == CODEC_M4A) pos_stsz = seek_m4a_stsz (&stszEntries); // returns the pos of atom stsz
28682864 return ;
28692865 }
2870- (void ) pos_stsz;
28712866
2872- availableBytes = 16 * 1024 ;
2867+ availableBytes = 16 * 1024 ; // set some large value
28732868
28742869 availableBytes = min (availableBytes, InBuff.writeSpace ());
28752870 availableBytes = min (availableBytes, audiofile.size () - byteCounter);
@@ -2893,24 +2888,40 @@ void Audio::processLocalFile() {
28932888 }
28942889 return ;
28952890 }
2896- # ifndef CONFIG_IDF_TARGET_ESP32S
2897- if ((InBuff.freeSpace () > maxFrameSize) && (m_file_size - byteCounter) > maxFrameSize) return ;
2898- # endif
28992891 else {
2892+ if ((InBuff.freeSpace () > maxFrameSize) && (m_file_size - byteCounter) > maxFrameSize){
2893+ // fill the buffer before playing
2894+ return ;
2895+ }
2896+
29002897 f_stream = true ;
29012898 AUDIO_INFO (" stream ready" );
29022899 if (m_f_Log) log_i (" m_audioDataStart %d" , m_audioDataStart);
2903- if (m_resumeFilePos){
2904- if (m_resumeFilePos < m_audioDataStart) m_resumeFilePos = m_audioDataStart;
2905- if (m_avr_bitrate) m_audioCurrentTime = ((m_resumeFilePos - m_audioDataStart) / m_avr_bitrate) * 8 ;
2906- audiofile.seek (m_resumeFilePos);
2907- InBuff.resetBuffer ();
2908- byteCounter = m_resumeFilePos;
2909- if (m_f_Log) log_i (" m_resumeFilePos %i" , m_resumeFilePos);
2910- }
29112900 }
29122901 }
29132902
2903+ if (m_resumeFilePos){
2904+ if (m_resumeFilePos < m_audioDataStart) m_resumeFilePos = m_audioDataStart;
2905+ if (m_resumeFilePos > m_file_size) m_resumeFilePos = m_file_size;
2906+ if (m_codec == CODEC_M4A) m_resumeFilePos = m4a_correctResumeFilePos (m_resumeFilePos);
2907+ if (m_codec == CODEC_WAV) {while ((m_resumeFilePos % 4 ) != 0 ) m_resumeFilePos++;} // must be divisible by four
2908+ if (m_codec == CODEC_FLAC) {m_resumeFilePos = flac_correctResumeFilePos (m_resumeFilePos); FLACDecoderReset ();}
2909+ if (m_codec == CODEC_MP3) {m_resumeFilePos = mp3_correctResumeFilePos (m_resumeFilePos);}
2910+ if (m_avr_bitrate) m_audioCurrentTime = ((m_resumeFilePos - m_audioDataStart) / m_avr_bitrate) * 8 ;
2911+ audiofile.seek (m_resumeFilePos);
2912+ InBuff.resetBuffer ();
2913+ byteCounter = m_resumeFilePos;
2914+
2915+ if (m_f_Log){
2916+ log_i (" m_resumeFilePos %d" , m_resumeFilePos);
2917+ log_i (" m_audioDataStart %d" , m_audioDataStart);
2918+ log_i (" m_audioCurrentTime %f" , (double )m_audioCurrentTime);
2919+ log_i (" m_file_size %d" , m_file_size);
2920+ }
2921+ m_resumeFilePos = 0 ;
2922+ f_stream = false ;
2923+ }
2924+
29142925 // end of file reached? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
29152926 if (f_fileDataComplete && InBuff.bufferFilled () < InBuff.getMaxBlockSize ()){
29162927 if (InBuff.bufferFilled ()){
@@ -4299,16 +4310,10 @@ bool Audio::setTimeOffset(int sec){
42994310// ---------------------------------------------------------------------------------------------------------------------
43004311bool Audio::setFilePos (uint32_t pos) {
43014312 if (!audiofile) return false ;
4302- // if(!m_avr_bitrate) return false;
4303- if (m_codec == CODEC_M4A) return false ;
4304- m_f_playing = false ;
4305- if (m_codec == CODEC_MP3) MP3Decoder_ClearBuffer ();
4306- if (m_codec == CODEC_WAV) {while ((pos % 4 ) != 0 ) pos++;} // must be divisible by four
4307- if (m_codec == CODEC_FLAC) FLACDecoderReset ();
4308- InBuff.resetBuffer ();
43094313 if (pos < m_audioDataStart) pos = m_audioDataStart; // issue #96
4310- if (m_avr_bitrate) m_audioCurrentTime = ((pos-m_audioDataStart) / m_avr_bitrate) * 8 ; // #96
4311- return audiofile.seek (pos);
4314+ if (pos > m_file_size) pos = m_file_size;
4315+ m_resumeFilePos = pos;
4316+ return true ;
43124317}
43134318// ---------------------------------------------------------------------------------------------------------------------
43144319bool Audio::audioFileSeek (const float speed) {
@@ -5117,7 +5122,7 @@ void Audio::lostStreamDetection(uint32_t bytesAvail){
51175122 else loopCnt = 0 ;
51185123}
51195124// ----------------------------------------------------------------------------------------------------------------------
5120- uint32_t Audio::seek_m4a_stsz (uint32_t * numEntries ){
5125+ void Audio::seek_m4a_stsz (){
51215126 // stsz says what size each sample is in bytes. This is important for the decoder to be able to start at a chunk,
51225127 // and then go through each sample by its size. The stsz atom can be behind the audio block. Therefore, searching
51235128 // for the stsz atom is only applicable to local files.
@@ -5159,8 +5164,9 @@ uint32_t Audio::seek_m4a_stsz(uint32_t* numEntries){
51595164 uint32_t seekpos = 0 ;
51605165 uint32_t filesize = getFileSize ();
51615166 char name[6 ][5 ] = {" moov" , " trak" , " mdia" , " minf" , " stbl" , " stsz" };
5167+ char noe[4 ];
51625168
5163- if (!audiofile) return 0 ; // guard
5169+ if (!audiofile) return ; // guard
51645170
51655171 at.pos = 0 ;
51665172 at.size = filesize;
@@ -5178,12 +5184,91 @@ uint32_t Audio::seek_m4a_stsz(uint32_t* numEntries){
51785184 seekpos = at.pos + 8 ; // 4 bytes size + 4 bytes name
51795185 }
51805186
5187+ seekpos += 8 ; // 1 byte version + 3 bytes flags + 4 bytes sample size
5188+ audiofile.seek (seekpos);
5189+ audiofile.readBytes (noe, 4 ); // number of entries
5190+ m_stsz_numEntries = bigEndian ((uint8_t *)noe, 4 );
5191+ if (m_f_Log) log_i (" number of entries in stsz: %d" , m_stsz_numEntries);
5192+ m_stsz_position = seekpos + 4 ;
51815193 audiofile.seek (0 );
5182- *numEntries = at.size / 4 ;
5183- return at.pos ;
5194+ return ;
51845195
51855196noSuccess:
5186- log_e (" error, returns 0" );
5197+ m_stsz_numEntries= 0 ;
5198+ m_stsz_position = 0 ;
5199+ log_e (" m4a atom stsz not found" );
51875200 audiofile.seek (0 );
5188- return 0 ;
5189- }
5201+ return ;
5202+ }
5203+ // ----------------------------------------------------------------------------------------------------------------------
5204+ uint32_t Audio::m4a_correctResumeFilePos (uint32_t resumeFilePos){
5205+ // In order to jump within an m4a file, the exact beginning of an aac block must be found. Since m4a cannot be
5206+ // streamed, i.e. there is no syncword, an imprecise jump can lead to a crash.
5207+
5208+ if (!m_stsz_position) return m_audioDataStart; // guard
5209+
5210+ typedef union {
5211+ uint8_t u8 [4 ];
5212+ uint32_t u32 ;
5213+ } tu;
5214+ tu uu;
5215+
5216+ uint32_t i = 0 , pos = m_audioDataStart;
5217+ audiofile.seek (m_stsz_position);
5218+
5219+ while (i < m_stsz_numEntries){
5220+ i++;
5221+ uu.u8 [3 ] = audiofile.read ();
5222+ uu.u8 [2 ] = audiofile.read ();
5223+ uu.u8 [1 ] = audiofile.read ();
5224+ uu.u8 [0 ] = audiofile.read ();
5225+ pos += uu.u32 ;
5226+ if (pos >= resumeFilePos) break ;
5227+ }
5228+ return pos;
5229+ }
5230+ // ----------------------------------------------------------------------------------------------------------------------
5231+ uint32_t Audio::flac_correctResumeFilePos (uint32_t resumeFilePos){
5232+ // The starting point is the next FLAC syncword
5233+ uint8_t p1, p2;
5234+ boolean found = false ;
5235+ uint32_t pos = resumeFilePos;
5236+ audiofile.seek (pos);
5237+
5238+ p1 = audiofile.read ();
5239+ p2 = audiofile.read ();
5240+ pos+=2 ;
5241+ while (!found || pos == m_file_size){
5242+ if (p1 == 0xFF && p2 == 0xF8 ){found = true ; log_i (" found" ); break ;}
5243+ p1 = p2;
5244+ p2 = audiofile.read ();
5245+ pos++;
5246+ }
5247+
5248+ if (found) return (pos - 2 );
5249+ return m_audioDataStart;
5250+ }
5251+ // ----------------------------------------------------------------------------------------------------------------------
5252+ uint32_t Audio::mp3_correctResumeFilePos (uint32_t resumeFilePos){
5253+ // The starting point is the next MP3 syncword
5254+ uint8_t p1, p2;
5255+ boolean found = false ;
5256+ uint32_t pos = resumeFilePos;
5257+ audiofile.seek (pos);
5258+
5259+ p1 = audiofile.read ();
5260+ p2 = audiofile.read ();
5261+ pos+=2 ;
5262+ while (!found || pos == m_file_size){
5263+ if (p1 == 0xFF && (p2 & 0xF0 ) == 0xF0 ){found = true ; break ;}
5264+ p1 = p2;
5265+ p2 = audiofile.read ();
5266+ pos++;
5267+ }
5268+
5269+ if (found) return (pos - 2 );
5270+ return m_audioDataStart;
5271+ }
5272+ // ----------------------------------------------------------------------------------------------------------------------
5273+
5274+
0 commit comments