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
cf8dea21
Unverified
Commit
cf8dea21
authored
Jan 27, 2023
by
Wolle
Committed by
GitHub
Jan 27, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add files via upload
parent
98defaa6
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
68 additions
and
54 deletions
+68
-54
src/opus_decoder/opus_decoder.cpp
src/opus_decoder/opus_decoder.cpp
+63
-52
src/opus_decoder/opus_decoder.h
src/opus_decoder/opus_decoder.h
+5
-2
No files found.
src/opus_decoder/opus_decoder.cpp
View file @
cf8dea21
...
...
@@ -3,21 +3,24 @@
* based on Xiph.Org Foundation celt decoder
*
* Created on: 26.01.2023
* Updated on:
* Updated on:
27.01.2023
************************************************************************************/
#include "opus_decoder.h"
// global vars
bool
f_m_magicWordFound
=
false
;
bool
f_m_firstPage
=
false
;
bool
f_m_commentHeader
=
false
;
bool
f_m_opusHeadWasRead
=
false
;
bool
f_m_nextPage
=
false
;
bool
f_m_newSt
=
false
;
// streamTitle
bool
f_m_opusFramePacket
=
false
;
uint8_t
m_channels
=
0
;
char
*
m_chbuf
=
NULL
;
bool
f_m_parseOgg
=
false
;
bool
f_m_subsequentPage
=
false
;
// bool f_m_commentHeader = false;
// bool f_m_opusHeadWasRead = false;
// bool f_m_nextPage = false;
bool
f_m_newSt
=
false
;
// streamTitle
bool
f_m_opusFramePacket
=
false
;
uint8_t
m_channels
=
0
;
uint16_t
m_samplerate
=
0
;
char
*
m_chbuf
=
NULL
;
std
::
vector
<
uint16_t
>
m_segmentTable
;
// contains segment frame lengths
bool
OPUSDecoder_AllocateBuffers
(){
...
...
@@ -32,18 +35,14 @@ void OPUSDecoder_FreeBuffers(){
//----------------------------------------------------------------------------------------------------------------------
int
OPUSDecode
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
){
if
(
f_m_magicWordFound
||
f_m_nextPage
||
f_m_opusHeadWasRead
){
log_w
(
"f_m_parseOgg %i"
,
f_m_parseOgg
);
if
(
f_m_parseOgg
==
true
){
log_i
(
"parseogg"
);
int
ret
=
OPUSparseOGG
(
inbuf
,
bytesLeft
);
f_m_parseOgg
=
false
;
return
ret
;
}
if
(
f_m_firstPage
){
int
ret
=
parseOpusHead
(
inbuf
,
bytesLeft
);
return
ret
;
}
if
(
f_m_commentHeader
){
int
ret
=
parseOpusComment
(
inbuf
,
bytesLeft
);
return
ret
;
}
if
(
f_m_opusFramePacket
){
int
ret
=
parseOpusFramePacket
(
inbuf
,
bytesLeft
);
...
...
@@ -58,7 +57,7 @@ uint8_t OPUSGetChannels(){
return
m_channels
;
}
uint32_t
OPUSGetSampRate
(){
return
48000
;
return
m_samplerate
;
}
uint8_t
OPUSGetBitsPerSample
(){
return
16
;
...
...
@@ -116,34 +115,30 @@ int parseOpusFramePacket(uint8_t *inbuf, int *bytesLeft){ // https://www.rfc-ed
return
0
;
}
//----------------------------------------------------------------------------------------------------------------------
int
parseOpusComment
(
uint8_t
*
inbuf
,
int
*
bytesLeft
){
// reference https://exiftool.org/TagNames/Vorbis.html#Comments
int
parseOpusComment
(
uint8_t
*
inbuf
,
int
nBytes
){
// reference https://exiftool.org/TagNames/Vorbis.html#Comments
// reference https://www.rfc-editor.org/rfc/rfc7845#section-5
int
idx
=
OPUS_specialIndexOf
(
inbuf
,
"OpusTags"
,
10
);
if
(
idx
!=
0
)
return
0
;
//ERR_OPUS_DECODER_ASYNC;
if
(
idx
!=
0
)
return
0
;
// is not OpusTags
char
*
artist
=
NULL
;
char
*
title
=
NULL
;
uint16_t
pos
=
8
;
*
bytesLeft
-=
8
;
uint32_t
vendorLength
=
*
(
inbuf
+
11
)
<<
24
;
// lengt of vendor string, e.g. Lavf58.65.101
vendorLength
+=
*
(
inbuf
+
10
)
<<
16
;
vendorLength
+=
*
(
inbuf
+
9
)
<<
8
;
vendorLength
+=
*
(
inbuf
+
8
);
pos
+=
vendorLength
+
4
;
*
bytesLeft
-=
(
vendorLength
+
4
);
uint32_t
commentListLength
=
*
(
inbuf
+
3
+
pos
)
<<
24
;
// nr. of comment entries
commentListLength
+=
*
(
inbuf
+
2
+
pos
)
<<
16
;
commentListLength
+=
*
(
inbuf
+
1
+
pos
)
<<
8
;
commentListLength
+=
*
(
inbuf
+
0
+
pos
);
pos
+=
4
;
*
bytesLeft
-=
4
;
for
(
int
i
=
0
;
i
<
commentListLength
;
i
++
){
uint32_t
commentStringLen
=
*
(
inbuf
+
3
+
pos
)
<<
24
;
commentStringLen
+=
*
(
inbuf
+
2
+
pos
)
<<
16
;
commentStringLen
+=
*
(
inbuf
+
1
+
pos
)
<<
8
;
commentStringLen
+=
*
(
inbuf
+
0
+
pos
);
pos
+=
4
;
*
bytesLeft
-=
4
;
idx
=
OPUS_specialIndexOf
(
inbuf
+
pos
,
"artist="
,
10
);
if
(
idx
==
0
){
artist
=
strndup
((
const
char
*
)(
inbuf
+
pos
+
7
),
commentStringLen
-
7
);
}
...
...
@@ -151,7 +146,6 @@ int parseOpusComment(uint8_t *inbuf, int *bytesLeft){ // reference https://exif
if
(
idx
==
0
){
title
=
strndup
((
const
char
*
)(
inbuf
+
pos
+
6
),
commentStringLen
-
6
);
}
pos
+=
commentStringLen
;
*
bytesLeft
-=
commentStringLen
;
}
if
(
artist
&&
title
){
strcpy
(
m_chbuf
,
artist
);
...
...
@@ -170,17 +164,13 @@ int parseOpusComment(uint8_t *inbuf, int *bytesLeft){ // reference https://exif
if
(
artist
){
free
(
artist
);
artist
=
NULL
;}
if
(
title
)
{
free
(
title
);
title
=
NULL
;}
f_m_commentHeader
=
false
;
f_m_nextPage
=
true
;
return
0
;
return
1
;
}
//----------------------------------------------------------------------------------------------------------------------
int
parseOpusHead
(
uint8_t
*
inbuf
,
int
*
bytesLeft
){
// reference https://wiki.xiph.org/OggOpus
int
parseOpusHead
(
uint8_t
*
inbuf
,
int
nBytes
){
// reference https://wiki.xiph.org/OggOpus
int
idx
=
OPUS_specialIndexOf
(
inbuf
,
"OpusHead"
,
10
);
if
(
idx
!=
0
)
return
0
;
//ERR_OPUS_DECODER_ASYNC;
if
(
idx
!=
0
)
return
0
;
//is not OpusHead
uint8_t
version
=
*
(
inbuf
+
8
);
(
void
)
version
;
uint8_t
channelCount
=
*
(
inbuf
+
9
);
// nr of channels
uint16_t
preSkip
=
*
(
inbuf
+
11
)
<<
8
;
...
...
@@ -199,18 +189,14 @@ int parseOpusHead(uint8_t *inbuf, int *bytesLeft){ // reference https://wiki.xi
if
(
channelMap
>
1
)
return
ERR_OPUS_EXTRA_CHANNELS_UNSUPPORTED
;
(
void
)
outputGain
;
f_m_opusHeadWasRead
=
true
;
// The next Opus packet MUST contain the comment header.
f_m_firstPage
=
false
;
f_m_nextPage
=
true
;
*
bytesLeft
-=
19
;
return
0
;
return
1
;
}
//----------------------------------------------------------------------------------------------------------------------
int
OPUSparseOGG
(
uint8_t
*
inbuf
,
int
*
bytesLeft
){
// reference https://www.xiph.org/ogg/doc/rfc3533.txt
int
ret
=
0
;
int
idx
=
OPUS_specialIndexOf
(
inbuf
,
"OggS"
,
6
);
log_i
(
"idx %i"
,
idx
);
if
(
idx
!=
0
)
return
0
;
//ERR_OPUS_DECODER_ASYNC;
...
...
@@ -238,14 +224,37 @@ int OPUSparseOGG(uint8_t *inbuf, int *bytesLeft){ // reference https://www.xiph
CRCchecksum
+=
*
(
inbuf
+
23
)
<<
8
;
CRCchecksum
+=
*
(
inbuf
+
22
);
(
void
)
CRCchecksum
;
uint8_t
pageSegments
=
*
(
inbuf
+
26
);
// giving the number of segment entries
uint8_t
segmentTable
=
*
(
inbuf
+
27
);
// number_page_segments
// read the segment table (contains pageSegments bytes), 1...251: Length of the frame in bytes,
// 255: A second byte is needed. The total length is first_byte + second byte
m_segmentTable
.
clear
();
for
(
int
i
=
0
;
i
<
pageSegments
;
i
++
){
if
(
*
(
inbuf
+
27
+
i
)
<
255
)
m_segmentTable
.
push_back
(
*
(
inbuf
+
27
+
i
));
else
{
m_segmentTable
.
push_back
(
*
(
inbuf
+
27
+
i
)
+
(
*
(
inbuf
+
27
+
i
+
1
)));
i
++
;
}
}
bool
continuedPage
=
headerType
&
0x01
;
// set: page contains data of a packet continued from the previous page
bool
firstPage
=
headerType
&
0x02
;
// set: this is the first page of a logical bitstream (bos)
bool
lastPage
=
headerType
&
0x04
;
// set: this is the last page of a logical bitstream (eos)
uint16_t
headerSize
=
pageSegments
+
27
;
(
void
)
continuedPage
;
(
void
)
lastPage
;
*
bytesLeft
-=
headerSize
;
(
void
)
segmentTable
;
(
void
)
continuedPage
;
(
void
)
lastPage
;
if
(
firstPage
||
f_m_subsequentPage
){
// OpusHead or OggComment may follows
ret
=
parseOpusHead
(
inbuf
+
headerSize
,
m_segmentTable
[
0
]);
if
(
ret
==
1
)
*
bytesLeft
-=
m_segmentTable
[
0
];
if
(
ret
<
0
){
*
bytesLeft
-=
m_segmentTable
[
0
];
return
ret
;}
ret
=
parseOpusComment
(
inbuf
+
headerSize
,
m_segmentTable
[
0
]);
if
(
ret
==
1
)
*
bytesLeft
-=
m_segmentTable
[
0
];
if
(
ret
<
0
){
*
bytesLeft
-=
m_segmentTable
[
0
];
return
ret
;}
f_m_parseOgg
=
true
;
// goto next page
log_i
(
"hier2"
);
}
if
(
firstPage
)
f_m_subsequentPage
=
true
;
else
f_m_subsequentPage
=
false
;
log_i
(
"headerType %i"
,
headerType
);
log_i
(
"firstPage %i"
,
firstPage
);
...
...
@@ -253,16 +262,18 @@ int OPUSparseOGG(uint8_t *inbuf, int *bytesLeft){ // reference https://www.xiph
log_i
(
"lastPage %i"
,
lastPage
);
log_i
(
"headerSize %i"
,
headerSize
);
log_i
(
"granulePosition %u"
,
granulePosition
);
if
(
firstPage
)
f_m_firstPage
=
true
;
// OpusHead follows
if
(
f_m_opusHeadWasRead
)
f_m_commentHeader
=
true
;
// OpusComment follows
log_i
(
"bitstreamSerialNr %u"
,
bitstreamSerialNr
);
log_i
(
"pageSequenceNr %u"
,
pageSequenceNr
);
log_i
(
"pageSegments %i"
,
pageSegments
);
if
(
!
f_m_firstPage
&&
!
f_m_commentHeader
)
f_m_opusFramePacket
=
true
;
// await opus frame packet
f_m_magicWordFound
=
false
;
f_m_nextPage
=
false
;
f_m_opusHeadWasRead
=
false
;
*
bytesLeft
-=
headerSize
;
int
sum
=
0
;
for
(
int
i
=
0
;
i
<
m_segmentTable
.
size
();
i
++
){
log_w
(
"segTable %i, sum %i"
,
m_segmentTable
[
i
],
sum
);
sum
+=
m_segmentTable
[
i
];
}
log_w
(
"sum = %i"
,
sum
);
log_w
(
"f_m_parseOgg %i"
,
f_m_parseOgg
);
return
0
;
// no error
}
...
...
@@ -272,10 +283,10 @@ int OPUSFindSyncWord(unsigned char *buf, int nBytes){
int
idx
=
OPUS_specialIndexOf
(
buf
,
"OggS"
,
nBytes
);
if
(
idx
>=
0
){
// Magic Word found
log_i
(
"OggS found at %i"
,
idx
);
f_m_
magicWordFound
=
true
;
f_m_
parseOgg
=
true
;
return
idx
;
}
f_m_
magicWordFound
=
false
;
f_m_
parseOgg
=
false
;
return
-
1
;
}
//----------------------------------------------------------------------------------------------------------------------
...
...
src/opus_decoder/opus_decoder.h
View file @
cf8dea21
...
...
@@ -4,6 +4,9 @@
//#pragma GCC diagnostic ignored "-Wnarrowing"
#include "Arduino.h"
#include <vector>
enum
:
int8_t
{
ERR_OPUS_NONE
=
0
,
ERR_OPUS_NR_OF_CHANNELS_UNSUPPORTED
=
-
1
,
...
...
@@ -26,8 +29,8 @@ uint16_t OPUSGetOutputSamps();
char
*
OPUSgetStreamTitle
();
int
OPUSFindSyncWord
(
unsigned
char
*
buf
,
int
nBytes
);
int
OPUSparseOGG
(
uint8_t
*
inbuf
,
int
*
bytesLeft
);
int
parseOpusHead
(
uint8_t
*
inbuf
,
int
*
bytesLeft
);
int
parseOpusComment
(
uint8_t
*
inbuf
,
int
*
bytesLeft
);
int
parseOpusHead
(
uint8_t
*
inbuf
,
int
nBytes
);
int
parseOpusComment
(
uint8_t
*
inbuf
,
int
nBytes
);
int
parseOpusFramePacket
(
uint8_t
*
inbuf
,
int
*
bytesLeft
);
// some helper functions
...
...
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