Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
ESP32-audioI2S
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
ESP32-audioI2S
Commits
985fa6e9
Commit
985fa6e9
authored
Apr 07, 2024
by
schreibfaul1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
better computeAudioTime() for WAV and FLAC
parent
2b54e39a
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
89 additions
and
54 deletions
+89
-54
src/Audio.cpp
src/Audio.cpp
+81
-48
src/Audio.h
src/Audio.h
+8
-6
No files found.
src/Audio.cpp
View file @
985fa6e9
...
...
@@ -3,8 +3,8 @@
*
* Created on: Oct 26.2018
*
* Version 3.0.9
a
* Updated on: Apr 0
4
.2024
* Version 3.0.9
b
* Updated on: Apr 0
7
.2024
* Author: Wolle (schreibfaul1)
*
*/
...
...
@@ -330,7 +330,7 @@ void Audio::setDefaults() {
m_f_metadata
=
false
;
m_f_tts
=
false
;
m_f_firstCall
=
true
;
// InitSequence for processWebstream and processLocalFile
m_f_firstCurTimeCall
=
true
;
// InitSequence for compute
_audioCurrent
Time
m_f_firstCurTimeCall
=
true
;
// InitSequence for compute
Audio
Time
m_f_firstM3U8call
=
true
;
// InitSequence for parsePlaylist_M3U8
m_f_running
=
false
;
m_f_loop
=
false
;
// Set if audio file should loop
...
...
@@ -364,6 +364,7 @@ void Audio::setDefaults() {
m_streamTitleHash
=
0
;
m_file_size
=
0
;
m_ID3Size
=
0
;
m_haveNewFilePos
=
0
;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
...
...
@@ -808,7 +809,7 @@ void Audio::UTF8toASCII(char* str) {
}
// clang-format on
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
bool
Audio
::
connecttoFS
(
fs
::
FS
&
fs
,
const
char
*
path
,
int32_t
resumeFile
Pos
)
{
bool
Audio
::
connecttoFS
(
fs
::
FS
&
fs
,
const
char
*
path
,
int32_t
fileStart
Pos
)
{
if
(
!
path
)
{
// guard
printProcessLog
(
AUDIOLOG_PATH_IS_NULL
);
...
...
@@ -817,7 +818,7 @@ bool Audio::connecttoFS(fs::FS& fs, const char* path, int32_t resumeFilePos) {
xSemaphoreTakeRecursive
(
mutex_audio
,
portMAX_DELAY
);
// #3
m_
resumeFilePos
=
resumeFile
Pos
;
m_
fileStartPos
=
fileStart
Pos
;
setDefaults
();
// free buffers an set defaults
char
*
audioPath
=
(
char
*
)
__malloc_heap_psram
(
strlen
(
path
)
+
2
);
...
...
@@ -3061,6 +3062,12 @@ void Audio::processLocalFile() {
if
(
m_f_Log
)
log_i
(
"m_audioDataStart %d"
,
m_audioDataStart
);
}
}
if
(
m_fileStartPos
>
0
){
setFilePos
(
m_fileStartPos
);
m_fileStartPos
=
-
1
;
}
if
(
m_resumeFilePos
>=
0
)
{
if
(
m_resumeFilePos
<
m_audioDataStart
)
m_resumeFilePos
=
m_audioDataStart
;
if
(
m_resumeFilePos
>
m_file_size
)
m_resumeFilePos
=
m_file_size
;
...
...
@@ -3073,11 +3080,11 @@ void Audio::processLocalFile() {
FLACDecoderReset
();
}
if
(
m_codec
==
CODEC_MP3
)
{
m_resumeFilePos
=
mp3_correctResumeFilePos
(
m_resumeFilePos
);
}
if
(
m_avr_bitrate
)
m_audioCurrentTime
=
((
double
)(
m_resumeFilePos
-
m_audioDataStart
)
/
m_avr_bitrate
)
*
8
;
audiofile
.
seek
(
m_resumeFilePos
);
InBuff
.
resetBuffer
();
byteCounter
=
m_resumeFilePos
;
f_fileDataComplete
=
false
;
// #570
m_haveNewFilePos
=
m_resumeFilePos
;
if
(
m_f_Log
)
{
log_i
(
"m_resumeFilePos %i"
,
m_resumeFilePos
);
...
...
@@ -4491,7 +4498,7 @@ int Audio::sendBytes(uint8_t* data, size_t len) {
uint16_t
bytesDecoderOut
=
m_validSamples
;
if
(
m_channels
==
2
)
bytesDecoderOut
/=
2
;
if
(
m_bitsPerSample
==
16
)
bytesDecoderOut
*=
2
;
compute
_audioCurrent
Time
(
bytesDecoded
,
bytesDecoderOut
);
compute
Audio
Time
(
bytesDecoded
,
bytesDecoderOut
);
if
(
audio_process_extern
)
{
bool
continueI2S
=
false
;
...
...
@@ -4503,18 +4510,20 @@ int Audio::sendBytes(uint8_t* data, size_t len) {
return
bytesDecoded
;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void
Audio
::
compute
_audioCurrent
Time
(
uint16_t
bytesDecoderIn
,
uint16_t
bytesDecoderOut
)
{
void
Audio
::
compute
Audio
Time
(
uint16_t
bytesDecoderIn
,
uint16_t
bytesDecoderOut
)
{
if
(
getDatamode
()
!=
AUDIO_LOCALFILE
&&
m_streamType
!=
ST_WEBFILE
)
return
;
//guard
static
uint64_t
sumBytesIn
=
0
;
static
uint64_t
sumBytesOut
=
0
;
static
uint32_t
sumBitRate
=
0
;
static
uint32_t
counter
=
0
;
static
uint32_t
timeStamp
=
0
;
static
uint32_t
deltaBytesIn
=
0
;
static
float
audioCurrentTime
=
0
;
float
compressionRatio
=
0
;
static
uint64_t
sumBytesIn
=
0
;
static
uint64_t
sumBytesOut
=
0
;
static
uint32_t
sumBitRate
=
0
;
static
uint32_t
counter
=
0
;
static
uint32_t
timeStamp
=
0
;
static
uint32_t
deltaBytesIn
=
0
;
static
uint32_t
constBitRate
=
0
;
static
uint32_t
playTime
=
0
;
static
uint32_t
totalPlayTime
=
0
;
float
compressionRatio
=
0
;
if
(
m_f_firstCurTimeCall
)
{
// first call
m_f_firstCurTimeCall
=
false
;
...
...
@@ -4524,7 +4533,20 @@ void Audio::compute_audioCurrentTime(uint16_t bytesDecoderIn, uint16_t bytesDeco
counter
=
0
;
timeStamp
=
millis
();
deltaBytesIn
=
0
;
audioCurrentTime
=
0
;
constBitRate
=
0
;
playTime
=
0
;
totalPlayTime
=
0
;
if
(
m_codec
==
CODEC_FLAC
&&
FLACGetAudioFileDuration
()){
m_audioFileDuration
=
FLACGetAudioFileDuration
();
constBitRate
=
(
m_audioDataSize
/
FLACGetAudioFileDuration
())
*
8
;
m_avr_bitrate
=
constBitRate
;
}
if
(
m_codec
==
CODEC_WAV
){
constBitRate
=
getBitRate
();
m_avr_bitrate
=
constBitRate
;
m_audioFileDuration
=
m_audioDataSize
/
(
getSampleRate
()
*
getChannels
());
if
(
getBitsPerSample
()
==
16
)
m_audioFileDuration
/=
2
;
}
}
sumBytesIn
+=
bytesDecoderIn
;
...
...
@@ -4532,24 +4554,37 @@ void Audio::compute_audioCurrentTime(uint16_t bytesDecoderIn, uint16_t bytesDeco
sumBytesOut
+=
bytesDecoderOut
;
if
(
timeStamp
+
950
<
millis
()){
uint32_t
t
=
millis
();
// time tracking
uint32_t
delta_t
=
t
-
timeStamp
;
// ---"---
playTime
+=
delta_t
;
// ---"---
totalPlayTime
+=
timeStamp
;
// ---"--- unused yet
timeStamp
=
t
;
// ---"---
// compressionRatio = (float)sumBytesIn / sumBytesOut;
(
void
)
compressionRatio
;
// unused yet
(
void
)
compressionRatio
;
// unused yet
uint32_t
t
=
millis
();
uint32_t
delta_t
=
t
-
timeStamp
;
timeStamp
=
t
;
// we know the time and bytesIn to compute the bitrate
uint32_t
bitRate
=
((
deltaBytesIn
*
8000
)
/
delta_t
);
uint32_t
bitRate
=
((
deltaBytesIn
*
8000
)
/
delta_t
);
// we know the time and bytesIn to compute the bitrate
sumBitRate
+=
bitRate
;
counter
++
;
m_avr_bitrate
=
sumBitRate
/
counter
;
audioCurrentTime
+=
((
float
)(
deltaBytesIn
*
8
)
/
m_avr_bitrate
);
m_audioCurrentTime
=
audioCurrentTime
;
if
(
constBitRate
){
m_audioCurrentTime
=
(
float
(
playTime
)
/
1000
);
}
else
{
m_avr_bitrate
=
sumBitRate
/
counter
;
m_audioCurrentTime
+=
((
float
)(
deltaBytesIn
*
8
)
/
m_avr_bitrate
);
m_audioFileDuration
=
8
*
((
float
)
m_audioDataSize
/
m_avr_bitrate
);
}
deltaBytesIn
=
0
;
}
if
(
m_haveNewFilePos
&&
m_avr_bitrate
){
uint32_t
posWhithinAudioBlock
=
m_haveNewFilePos
-
m_audioDataStart
;
uint32_t
newTime
=
posWhithinAudioBlock
/
(
m_avr_bitrate
/
8
);
// (m_avr_bitrate / 8) equals one second
m_audioCurrentTime
=
newTime
;
playTime
=
newTime
*
1000
;
// playTime[ms]
m_haveNewFilePos
=
0
;
}
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
void
Audio
::
printProcessLog
(
int
r
,
const
char
*
s
){
...
...
@@ -4743,11 +4778,11 @@ uint32_t Audio::getAudioFileDuration() {
}
if
(
!
m_avr_bitrate
)
return
0
;
return
m_audioFileDuration
=
8
*
((
float
)
m_audioDataSize
/
m_avr_bitrate
)
;
return
m_audioFileDuration
;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
uint32_t
Audio
::
getAudioCurrentTime
()
{
// return current time in seconds
return
(
uint32_t
)
m_audioCurrentTime
;
return
round
(
m_audioCurrentTime
)
;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
bool
Audio
::
setAudioPlayPosition
(
uint16_t
sec
)
{
...
...
@@ -4773,39 +4808,37 @@ uint32_t Audio::getTotalPlayingTime() {
return
millis
()
-
m_PlayingStartTime
;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
bool
Audio
::
setTimeOffset
(
int
sec
)
{
if
(
m_codec
==
CODEC_OPUS
)
return
false
;
// not impl. yet
if
(
m_codec
==
CODEC_VORBIS
)
return
false
;
// not impl. yet
// fast forward or rewind the current position in seconds
// audiosource must be a mp3, aac or wav file
bool
Audio
::
setTimeOffset
(
int
sec
)
{
// fast forward or rewind the current position in seconds
if
(
!
audiofile
||
!
m_avr_bitrate
)
return
false
;
if
(
m_codec
==
CODEC_OPUS
)
return
false
;
// not impl. yet
if
(
m_codec
==
CODEC_VORBIS
)
return
false
;
// not impl. yet
uint32_t
oneSec
=
m_avr_bitrate
/
8
;
// bytes decoded in one sec
int32_t
offset
=
oneSec
*
sec
;
// bytes to be wind/rewind
uint32_t
startAB
=
m_audioDataStart
;
// audioblock begin
uint32_t
endAB
=
m_audioDataStart
+
m_audioDataSize
;
// audioblock end
if
(
m_codec
==
CODEC_MP3
||
m_codec
==
CODEC_AAC
||
m_codec
==
CODEC_WAV
||
m_codec
==
CODEC_FLAC
)
{
int32_t
pos
=
getFilePos
()
-
inBufferFilled
();
pos
+=
offset
;
if
(
pos
<
(
int32_t
)
startAB
)
pos
=
startAB
;
if
(
pos
>=
(
int32_t
)
endAB
)
pos
=
endAB
;
setFilePos
(
pos
);
return
true
;
}
return
false
;
int32_t
pos
=
getFilePos
()
-
inBufferFilled
();
pos
+=
offset
;
if
(
pos
<
(
int32_t
)
startAB
)
{
pos
=
startAB
;}
if
(
pos
>=
(
int32_t
)
endAB
)
{
pos
=
endAB
;}
setFilePos
(
pos
);
return
true
;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
bool
Audio
::
setFilePos
(
uint32_t
pos
)
{
if
(
!
audiofile
)
return
false
;
if
(
m_codec
==
CODEC_OPUS
)
return
false
;
// not impl. yet
if
(
m_codec
==
CODEC_VORBIS
)
return
false
;
// not impl. yet
if
(
!
audiofile
)
return
false
;
if
(
pos
<
m_audioDataStart
)
pos
=
m_audioDataStart
;
// issue #96
if
(
pos
>
m_file_size
)
{
pos
=
m_file_size
;
stopSong
();
return
false
;}
m_resumeFilePos
=
pos
;
if
(
pos
<
m_audioDataStart
)
{
pos
=
m_audioDataStart
;}
if
(
pos
>
m_audioDataStart
+
m_audioDataSize
)
{
pos
=
m_audioDataStart
+
m_audioDataSize
;
stopSong
();
return
false
;}
memset
(
m_outBuff
,
0
,
m_outbuffSize
);
m_validSamples
=
0
;
m_resumeFilePos
=
pos
;
// used in processLocalFile()
m_haveNewFilePos
=
pos
;
// used in computeAudioCurrentTime()
return
true
;
}
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
...
...
src/Audio.h
View file @
985fa6e9
...
...
@@ -3,8 +3,8 @@
*
* Created on: Oct 28,2018
*
* Version 3.0.9
a
* Updated on: Apr 0
4
.2024
* Version 3.0.9
b
* Updated on: Apr 0
7
.2024
* Author: Wolle (schreibfaul1)
*/
...
...
@@ -136,7 +136,7 @@ public:
bool
openai_speech
(
const
String
&
api_key
,
const
String
&
model
,
const
String
&
input
,
const
String
&
voice
,
const
String
&
response_format
,
const
String
&
speed
);
bool
connecttohost
(
const
char
*
host
,
const
char
*
user
=
""
,
const
char
*
pwd
=
""
);
bool
connecttospeech
(
const
char
*
speech
,
const
char
*
lang
);
bool
connecttoFS
(
fs
::
FS
&
fs
,
const
char
*
path
,
int32_t
resumeFile
Pos
=
-
1
);
bool
connecttoFS
(
fs
::
FS
&
fs
,
const
char
*
path
,
int32_t
m_fileStart
Pos
=
-
1
);
bool
setFileLoop
(
bool
input
);
//TEST loop
void
setConnectionTimeout
(
uint16_t
timeout_ms
,
uint16_t
timeout_ms_ssl
);
bool
setAudioPlayPosition
(
uint16_t
sec
);
...
...
@@ -210,7 +210,7 @@ private:
int
findNextSync
(
uint8_t
*
data
,
size_t
len
);
int
sendBytes
(
uint8_t
*
data
,
size_t
len
);
void
setDecoderItems
();
void
compute
_audioCurrent
Time
(
uint16_t
bytesDecoderIn
,
uint16_t
bytesDecoderOut
);
void
compute
Audio
Time
(
uint16_t
bytesDecoderIn
,
uint16_t
bytesDecoderOut
);
void
printProcessLog
(
int
r
,
const
char
*
s
=
""
);
void
printDecodeError
(
int
r
);
void
showID3Tag
(
const
char
*
tag
,
const
char
*
val
);
...
...
@@ -543,17 +543,19 @@ private:
uint32_t
m_contentlength
=
0
;
// Stores the length if the stream comes from fileserver
uint32_t
m_bytesNotDecoded
=
0
;
// pictures or something else that comes with the stream
uint32_t
m_PlayingStartTime
=
0
;
// Stores the milliseconds after the start of the audio
int32_t
m_resumeFilePos
=
-
1
;
// the return value from stopSong() can be entered here, (-1) is idle
int32_t
m_resumeFilePos
=
-
1
;
// the return value from stopSong(), (-1) is idle
int32_t
m_fileStartPos
=
-
1
;
// may be set in connecttoFS()
uint16_t
m_m3u8_targetDuration
=
10
;
//
uint32_t
m_stsz_numEntries
=
0
;
// num of entries inside stsz atom (uint32_t)
uint32_t
m_stsz_position
=
0
;
// pos of stsz atom within file
uint32_t
m_haveNewFilePos
=
0
;
// user changed the file position
bool
m_f_metadata
=
false
;
// assume stream without metadata
bool
m_f_unsync
=
false
;
// set within ID3 tag but not used
bool
m_f_exthdr
=
false
;
// ID3 extended header
bool
m_f_ssl
=
false
;
bool
m_f_running
=
false
;
bool
m_f_firstCall
=
false
;
// InitSequence for processWebstream and processLokalFile
bool
m_f_firstCurTimeCall
=
false
;
// InitSequence for compute
_audioCurrent
Time
bool
m_f_firstCurTimeCall
=
false
;
// InitSequence for compute
Audio
Time
bool
m_f_firstM3U8call
=
false
;
// InitSequence for m3u8 parsing
bool
m_f_chunked
=
false
;
// Station provides chunked transfer
bool
m_f_firstmetabyte
=
false
;
// True if first metabyte (counter)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment