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
be305923
Unverified
Commit
be305923
authored
Jan 10, 2023
by
Wolle
Committed by
GitHub
Jan 10, 2023
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #459 from schreibfaul1/master
keep the test branch up to date
parents
18c3a70b
32385d0a
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
148 additions
and
31 deletions
+148
-31
src/Audio.cpp
src/Audio.cpp
+143
-29
src/Audio.h
src/Audio.h
+3
-1
src/aac_decoder/aac_decoder.cpp
src/aac_decoder/aac_decoder.cpp
+2
-1
No files found.
src/Audio.cpp
View file @
be305923
...
...
@@ -3,8 +3,8 @@
*
* Created on: Oct 26.2018
*
* Version 2.0.8
* Updated on: Jan
09
.2023
* Version 2.0.8
b
* Updated on: Jan
10
.2023
* Author: Wolle (schreibfaul1)
*
*/
...
...
@@ -338,6 +338,7 @@ void Audio::setDefaults() {
m_f_m3u8data
=
false
;
// set again in processM3U8entries() if necessary
m_f_continue
=
false
;
m_f_ts
=
false
;
m_f_m4aID3dataAreRead
=
false
;
m_streamType
=
ST_NONE
;
m_codec
=
CODEC_NONE
;
...
...
@@ -1823,9 +1824,10 @@ int Audio::read_M4A_Header(uint8_t *data, size_t len) {
}
int
m4a
=
specialIndexOf
(
data
,
"M4A "
,
20
);
int
isom
=
specialIndexOf
(
data
,
"isom"
,
20
);
int
mp42
=
specialIndexOf
(
data
,
"mp42"
,
20
);
if
((
m4a
!=
8
)
&&
(
isom
!=
8
)){
log_e
(
"subtype 'MA4 '
or 'isom
' expected, but found '%s '"
,
(
data
+
8
));
if
((
m4a
!=
8
)
&&
(
isom
!=
8
)
&&
(
mp42
!=
8
)
){
log_e
(
"subtype 'MA4 '
, 'isom' or 'mp42
' expected, but found '%s '"
,
(
data
+
8
));
stopSong
();
return
-
1
;
}
...
...
@@ -1975,30 +1977,34 @@ int Audio::read_M4A_Header(uint8_t *data, size_t len) {
const
char
info
[
12
][
6
]
=
{
"nam
\0
"
,
"ART
\0
"
,
"alb
\0
"
,
"too
\0
"
,
"cmt
\0
"
,
"wrt
\0
"
,
"tmpo
\0
"
,
"trkn
\0
"
,
"day
\0
"
,
"cpil
\0
"
,
"aART
\0
"
,
"gen
\0
"
};
int
offset
;
for
(
int
i
=
0
;
i
<
12
;
i
++
){
offset
=
specialIndexOf
(
data
,
info
[
i
],
len
,
true
);
// seek info[] with '\0'
if
(
offset
>
0
)
{
offset
+=
19
;
if
(
*
(
data
+
offset
)
==
0
)
offset
++
;
char
value
[
256
];
size_t
tmp
=
strlen
((
const
char
*
)
data
+
offset
);
if
(
tmp
>
254
)
tmp
=
254
;
memcpy
(
value
,
(
data
+
offset
),
tmp
);
value
[
tmp
]
=
0
;
m_chbuf
[
0
]
=
0
;
if
(
i
==
0
)
sprintf
(
m_chbuf
,
"Title: %s"
,
value
);
if
(
i
==
1
)
sprintf
(
m_chbuf
,
"Artist: %s"
,
value
);
if
(
i
==
2
)
sprintf
(
m_chbuf
,
"Album: %s"
,
value
);
if
(
i
==
3
)
sprintf
(
m_chbuf
,
"Encoder: %s"
,
value
);
if
(
i
==
4
)
sprintf
(
m_chbuf
,
"Comment: %s"
,
value
);
if
(
i
==
5
)
sprintf
(
m_chbuf
,
"Composer: %s"
,
value
);
if
(
i
==
6
)
sprintf
(
m_chbuf
,
"BPM: %s"
,
value
);
if
(
i
==
7
)
sprintf
(
m_chbuf
,
"Track Number: %s"
,
value
);
if
(
i
==
8
)
sprintf
(
m_chbuf
,
"Year: %s"
,
value
);
if
(
i
==
9
)
sprintf
(
m_chbuf
,
"Compile: %s"
,
value
);
if
(
i
==
10
)
sprintf
(
m_chbuf
,
"Album Artist: %s"
,
value
);
if
(
i
==
11
)
sprintf
(
m_chbuf
,
"Types of: %s"
,
value
);
if
(
m_chbuf
[
0
]
!=
0
)
{
if
(
audio_id3data
)
audio_id3data
(
m_chbuf
);
// If it's a local file, the metadata has already been read, even if it comes after the audio block.
// In the event that they are in front of the audio block in a web stream, read them now
if
(
!
m_f_m4aID3dataAreRead
){
for
(
int
i
=
0
;
i
<
12
;
i
++
){
offset
=
specialIndexOf
(
data
,
info
[
i
],
len
,
true
);
// seek info[] with '\0'
if
(
offset
>
0
)
{
offset
+=
19
;
if
(
*
(
data
+
offset
)
==
0
)
offset
++
;
char
value
[
256
];
size_t
tmp
=
strlen
((
const
char
*
)
data
+
offset
);
if
(
tmp
>
254
)
tmp
=
254
;
memcpy
(
value
,
(
data
+
offset
),
tmp
);
value
[
tmp
]
=
0
;
m_chbuf
[
0
]
=
0
;
if
(
i
==
0
)
sprintf
(
m_chbuf
,
"Title: %s"
,
value
);
if
(
i
==
1
)
sprintf
(
m_chbuf
,
"Artist: %s"
,
value
);
if
(
i
==
2
)
sprintf
(
m_chbuf
,
"Album: %s"
,
value
);
if
(
i
==
3
)
sprintf
(
m_chbuf
,
"Encoder: %s"
,
value
);
if
(
i
==
4
)
sprintf
(
m_chbuf
,
"Comment: %s"
,
value
);
if
(
i
==
5
)
sprintf
(
m_chbuf
,
"Composer: %s"
,
value
);
if
(
i
==
6
)
sprintf
(
m_chbuf
,
"BPM: %s"
,
value
);
if
(
i
==
7
)
sprintf
(
m_chbuf
,
"Track Number: %s"
,
value
);
if
(
i
==
8
)
sprintf
(
m_chbuf
,
"Year: %s"
,
value
);
if
(
i
==
9
)
sprintf
(
m_chbuf
,
"Compile: %s"
,
value
);
if
(
i
==
10
)
sprintf
(
m_chbuf
,
"Album Artist: %s"
,
value
);
if
(
i
==
11
)
sprintf
(
m_chbuf
,
"Types of: %s"
,
value
);
if
(
m_chbuf
[
0
]
!=
0
)
{
if
(
audio_id3data
)
audio_id3data
(
m_chbuf
);
}
}
}
}
...
...
@@ -2680,6 +2686,8 @@ void Audio::processLocalFile() {
f_stream
=
false
;
f_fileDataComplete
=
false
;
byteCounter
=
0
;
if
(
m_codec
==
CODEC_M4A
)
seek_m4a_stsz
();
// determine the pos of atom stsz
if
(
m_codec
==
CODEC_M4A
)
seek_m4a_ilst
();
// looking for metadata
return
;
}
...
...
@@ -4900,6 +4908,111 @@ boolean Audio::streamDetection(uint32_t bytesAvail){
return
false
;
}
//----------------------------------------------------------------------------------------------------------------------
void
Audio
::
seek_m4a_ilst
(){
// ilist - item list atom, contains the metadata
/* atom hierarchy (example)_________________________________________________________________________________________
ftyp -> moov -> udta -> meta -> ilst -> data
__________________________________________________________________________________________________________________*/
struct
m4a_Atom
{
int
pos
;
int
size
;
char
name
[
5
];
}
atom
,
at
,
tmp
;
// c99 has no inner functions, lambdas are only allowed from c11, please don't use ancient compiler
auto
atomItems
=
[
&
](
uint32_t
startPos
){
// lambda, inner function
char
tmp
[
5
];
audiofile
.
seek
(
startPos
);
audiofile
.
readBytes
(
tmp
,
4
);
atom
.
size
=
bigEndian
((
uint8_t
*
)
tmp
,
4
);
if
(
!
atom
.
size
)
atom
.
size
=
4
;
// has no data, length is 0
audiofile
.
readBytes
(
atom
.
name
,
4
);
atom
.
name
[
4
]
=
'\0'
;
atom
.
pos
=
startPos
;
return
atom
;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
boolean
found
=
false
;
uint32_t
seekpos
=
0
;
uint32_t
filesize
=
getFileSize
();
char
name
[
6
][
5
]
=
{
"moov"
,
"udta"
,
"meta"
,
"ilst"
};
const
char
info
[
12
][
6
]
=
{
"nam
\0
"
,
"ART
\0
"
,
"alb
\0
"
,
"too
\0
"
,
"cmt
\0
"
,
"wrt
\0
"
,
"tmpo
\0
"
,
"trkn
\0
"
,
"day
\0
"
,
"cpil
\0
"
,
"aART
\0
"
,
"gen
\0
"
};
if
(
!
audiofile
)
return
;
// guard
at
.
pos
=
0
;
at
.
size
=
filesize
;
seekpos
=
0
;
for
(
int
i
=
0
;
i
<
4
;
i
++
){
found
=
false
;
while
(
seekpos
<
at
.
pos
+
at
.
size
){
tmp
=
atomItems
(
seekpos
);
seekpos
+=
tmp
.
size
;
if
(
strcmp
(
tmp
.
name
,
name
[
i
])
==
0
)
{
memcpy
((
void
*
)
&
at
,
(
void
*
)
&
tmp
,
sizeof
(
tmp
));
found
=
true
;}
log_i
(
"name %s pos %d, size %d"
,
tmp
.
name
,
tmp
.
pos
,
tmp
.
size
);
}
if
(
!
found
){
log_w
(
"m4a atom ilst not found"
);
audiofile
.
seek
(
0
);
return
;
}
seekpos
=
at
.
pos
+
8
;
// 4 bytes size + 4 bytes name
}
int
len
=
tmp
.
size
-
8
;
if
(
len
>
1024
)
len
=
1024
;
log_i
(
"found at pos %i, len %i"
,
seekpos
,
len
);
uint8_t
*
data
=
(
uint8_t
*
)
malloc
(
len
);
if
(
!
data
){
log_e
(
"out od memory"
);
audiofile
.
seek
(
0
);
return
;
}
audiofile
.
seek
(
seekpos
);
audiofile
.
read
(
data
,
len
);
int
offset
;
for
(
int
i
=
0
;
i
<
12
;
i
++
){
offset
=
specialIndexOf
(
data
,
info
[
i
],
len
,
true
);
// seek info[] with '\0'
if
(
offset
>
0
)
{
offset
+=
19
;
if
(
*
(
data
+
offset
)
==
0
)
offset
++
;
char
value
[
256
];
size_t
tmp
=
strlen
((
const
char
*
)
data
+
offset
);
if
(
tmp
>
254
)
tmp
=
254
;
memcpy
(
value
,
(
data
+
offset
),
tmp
);
value
[
tmp
]
=
0
;
m_chbuf
[
0
]
=
0
;
if
(
i
==
0
)
sprintf
(
m_chbuf
,
"Title: %s"
,
value
);
if
(
i
==
1
)
sprintf
(
m_chbuf
,
"Artist: %s"
,
value
);
if
(
i
==
2
)
sprintf
(
m_chbuf
,
"Album: %s"
,
value
);
if
(
i
==
3
)
sprintf
(
m_chbuf
,
"Encoder: %s"
,
value
);
if
(
i
==
4
)
sprintf
(
m_chbuf
,
"Comment: %s"
,
value
);
if
(
i
==
5
)
sprintf
(
m_chbuf
,
"Composer: %s"
,
value
);
if
(
i
==
6
)
sprintf
(
m_chbuf
,
"BPM: %s"
,
value
);
if
(
i
==
7
)
sprintf
(
m_chbuf
,
"Track Number: %s"
,
value
);
if
(
i
==
8
)
sprintf
(
m_chbuf
,
"Year: %s"
,
value
);
if
(
i
==
9
)
sprintf
(
m_chbuf
,
"Compile: %s"
,
value
);
if
(
i
==
10
)
sprintf
(
m_chbuf
,
"Album Artist: %s"
,
value
);
if
(
i
==
11
)
sprintf
(
m_chbuf
,
"Types of: %s"
,
value
);
if
(
m_chbuf
[
0
]
!=
0
)
{
if
(
audio_id3data
)
audio_id3data
(
m_chbuf
);
}
}
}
m_f_m4aID3dataAreRead
=
true
;
if
(
data
)
free
(
data
);
audiofile
.
seek
(
0
);
return
;
}
//----------------------------------------------------------------------------------------------------------------------
void
Audio
::
seek_m4a_stsz
(){
// stsz says what size each sample is in bytes. This is important for the decoder to be able to start at a chunk,
// and then go through each sample by its size. The stsz atom can be behind the audio block. Therefore, searching
...
...
@@ -4909,7 +5022,7 @@ void Audio::seek_m4a_stsz(){
ftyp -> moov -> trak -> tkhd
free udta mdia -> mdhd
mdat
udta
hdlr
mdat
hdlr
mvhd minf -> smhd
dinf
stbl -> stsd
...
...
@@ -4931,6 +5044,7 @@ void Audio::seek_m4a_stsz(){
audiofile
.
seek
(
startPos
);
audiofile
.
readBytes
(
tmp
,
4
);
atom
.
size
=
bigEndian
((
uint8_t
*
)
tmp
,
4
);
if
(
!
atom
.
size
)
atom
.
size
=
4
;
// has no data, length is 0
audiofile
.
readBytes
(
atom
.
name
,
4
);
atom
.
name
[
4
]
=
'\0'
;
atom
.
pos
=
startPos
;
...
...
src/Audio.h
View file @
be305923
...
...
@@ -2,7 +2,7 @@
* Audio.h
*
* Created on: Oct 28,2018
* Updated on: Jan
09
,2023
* Updated on: Jan
10
,2023
* Author: Wolle (schreibfaul1)
*/
...
...
@@ -274,6 +274,7 @@ private:
bool
readID3V1Tag
();
boolean
streamDetection
(
uint32_t
bytesAvail
);
void
seek_m4a_stsz
();
void
seek_m4a_ilst
();
uint32_t
m4a_correctResumeFilePos
(
uint32_t
resumeFilePos
);
uint32_t
flac_correctResumeFilePos
(
uint32_t
resumeFilePos
);
uint32_t
mp3_correctResumeFilePos
(
uint32_t
resumeFilePos
);
...
...
@@ -547,6 +548,7 @@ private:
bool
m_f_Log
=
false
;
// set in platformio.ini -DAUDIO_LOG and -DCORE_DEBUG_LEVEL=3 or 4
bool
m_f_continue
=
false
;
// next m3u8 chunk is available
bool
m_f_ts
=
true
;
// transport stream
bool
m_f_m4aID3dataAreRead
=
false
;
// has the m4a-ID3data already been read?
uint8_t
m_f_channelEnabled
=
3
;
// internal DAC, both channels
uint32_t
m_audioFileDuration
=
0
;
float
m_audioCurrentTime
=
0
;
...
...
src/aac_decoder/aac_decoder.cpp
View file @
be305923
...
...
@@ -3,7 +3,7 @@
* libhelix_HAACDECODER
*
* Created on: 26.10.2018
* Updated on:
22.12.2022
* Updated on:
09.01.2023
************************************************************************************/
#include "aac_decoder.h"
...
...
@@ -1978,6 +1978,7 @@ int AACDecode(uint8_t *inbuf, int *bytesLeft, short *outbuf)
do
{
/* parse next syntactic element */
if
(
bitsAvail
<
0
)
return
ERR_AAC_INDATA_UNDERFLOW
;
err
=
DecodeNextElement
(
&
inptr
,
&
bitOffset
,
&
bitsAvail
);
if
(
err
)
return
err
;
...
...
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