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
384ba4d5
Commit
384ba4d5
authored
Feb 10, 2024
by
schreibfaul1
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
impl countCode 1 and 2
parent
a48d33c8
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
317 additions
and
70 deletions
+317
-70
src/opus_decoder/opus_decoder.cpp
src/opus_decoder/opus_decoder.cpp
+310
-68
src/opus_decoder/opus_decoder.h
src/opus_decoder/opus_decoder.h
+7
-2
No files found.
src/opus_decoder/opus_decoder.cpp
View file @
384ba4d5
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
* based on Xiph.Org Foundation celt decoder
* based on Xiph.Org Foundation celt decoder
*
*
* Created on: 26.01.2023
* Created on: 26.01.2023
* Updated on:
08
.02.2024
* Updated on:
10
.02.2024
*/
*/
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
// O G G / O P U S I M P L.
// O G G / O P U S I M P L.
...
@@ -100,11 +100,8 @@ void OPUSsetDefaults(){
...
@@ -100,11 +100,8 @@ void OPUSsetDefaults(){
int
OPUSDecode
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
){
int
OPUSDecode
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
){
const
uint32_t
CELT_SET_END_BAND_REQUEST
=
10012
;
const
uint32_t
CELT_SET_END_BAND_REQUEST
=
10012
;
static
uint16_t
fs
=
0
;
static
uint8_t
frameCount
=
0
;
static
uint8_t
M
=
0
;
static
int8_t
configNr
=
0
;
static
uint8_t
configNr
=
31
;
// FULLBAND
static
uint16_t
paddingBytes
=
0
;
uint8_t
paddingLength
=
0
;
uint8_t
endband
=
21
;
uint8_t
endband
=
21
;
static
uint16_t
samplesPerFrame
=
0
;
static
uint16_t
samplesPerFrame
=
0
;
int
ret
=
ERR_OPUS_NONE
;
int
ret
=
ERR_OPUS_NONE
;
...
@@ -112,10 +109,9 @@ int OPUSDecode(uint8_t *inbuf, int *bytesLeft, short *outbuf){
...
@@ -112,10 +109,9 @@ int OPUSDecode(uint8_t *inbuf, int *bytesLeft, short *outbuf){
if
(
s_f_opusParseOgg
){
if
(
s_f_opusParseOgg
){
s_f_opusParseOgg
=
false
;
s_f_opusParseOgg
=
false
;
fs
=
0
;
frameCount
=
0
;
M
=
0
;
paddingBytes
=
0
;
s_opusCountCode
=
0
;
s_opusCountCode
=
0
;
samplesPerFrame
=
0
;
ret
=
OPUSparseOGG
(
inbuf
,
bytesLeft
);
ret
=
OPUSparseOGG
(
inbuf
,
bytesLeft
);
if
(
ret
!=
ERR_OPUS_NONE
)
return
ret
;
// error
if
(
ret
!=
ERR_OPUS_NONE
)
return
ret
;
// error
inbuf
+=
s_opusOggHeaderSize
;
inbuf
+=
s_opusOggHeaderSize
;
...
@@ -157,6 +153,9 @@ processChunk: // we can't return more than 2* 4096 bytes at a time (max OPUS
...
@@ -157,6 +153,9 @@ processChunk: // we can't return more than 2* 4096 bytes at a time (max OPUS
s_f_nextChunk
=
false
;
s_f_nextChunk
=
false
;
opusSegmentLength
=
s_opusSegmentLength
;
opusSegmentLength
=
s_opusSegmentLength
;
}
}
else
{
opusSegmentLength
=
0
;
}
// log_i("page(2) opusSegmentLength %i, s_opusRemainBlockPicLen %i", opusSegmentLength, s_opusRemainBlockPicLen);
// log_i("page(2) opusSegmentLength %i, s_opusRemainBlockPicLen %i", opusSegmentLength, s_opusRemainBlockPicLen);
if
(
s_opusRemainBlockPicLen
<=
0
&&
opusSegmentLength
<=
0
){
if
(
s_opusRemainBlockPicLen
<=
0
&&
opusSegmentLength
<=
0
){
...
@@ -206,8 +205,6 @@ processChunk: // we can't return more than 2* 4096 bytes at a time (max OPUS
...
@@ -206,8 +205,6 @@ processChunk: // we can't return more than 2* 4096 bytes at a time (max OPUS
}
}
log_e
(
"never reach this!"
);
log_e
(
"never reach this!"
);
}
}
if
(
s_opusCountCode
>
0
)
goto
FramePacking
;
// more than one frame in the packet
if
(
s_opusCountCode
>
0
)
goto
FramePacking
;
// more than one frame in the packet
if
(
s_opusSegmentTableSize
>
0
){
if
(
s_opusSegmentTableSize
>
0
){
...
@@ -217,6 +214,7 @@ processChunk: // we can't return more than 2* 4096 bytes at a time (max OPUS
...
@@ -217,6 +214,7 @@ processChunk: // we can't return more than 2* 4096 bytes at a time (max OPUS
}
}
configNr
=
parseOpusTOC
(
inbuf
[
0
]);
configNr
=
parseOpusTOC
(
inbuf
[
0
]);
if
(
configNr
<
0
)
return
configNr
;
// SILK or Hybrid mode
samplesPerFrame
=
opus_packet_get_samples_per_frame
(
inbuf
,
s_opusSamplerate
);
samplesPerFrame
=
opus_packet_get_samples_per_frame
(
inbuf
,
s_opusSamplerate
);
switch
(
configNr
){
switch
(
configNr
){
case
16
...
19
:
endband
=
13
;
// OPUS_BANDWIDTH_NARROWBAND
case
16
...
19
:
endband
=
13
;
// OPUS_BANDWIDTH_NARROWBAND
...
@@ -227,88 +225,332 @@ processChunk: // we can't return more than 2* 4096 bytes at a time (max OPUS
...
@@ -227,88 +225,332 @@ processChunk: // we can't return more than 2* 4096 bytes at a time (max OPUS
break
;
break
;
case
28
...
31
:
endband
=
21
;
// OPUS_BANDWIDTH_FULLBAND
case
28
...
31
:
endband
=
21
;
// OPUS_BANDWIDTH_FULLBAND
break
;
break
;
default:
log_e
(
"unknown bandwidth, configNr is: %i"
,
configNr
);
default:
log_e
(
"unknown bandwidth, configNr is: %d"
,
configNr
);
endband
=
21
;
// assume OPUS_BANDWIDTH_FULLBAND
break
;
break
;
}
}
celt_decoder_ctl
(
CELT_SET_END_BAND_REQUEST
,
endband
);
celt_decoder_ctl
(
CELT_SET_END_BAND_REQUEST
,
endband
);
FramePacking:
// https://www.tech-invite.com/y65/tinv-ietf-rfc-6716-2.html 3.2. Frame Packing
FramePacking:
// https://www.tech-invite.com/y65/tinv-ietf-rfc-6716-2.html 3.2. Frame Packing
switch
(
s_opusCountCode
){
switch
(
s_opusCountCode
){
case
0
:
// Code 0: One Frame in the Packet
case
0
:
// Code 0: One Frame in the Packet
*
bytesLeft
-=
len
;
ret
=
opus_FramePacking_Code0
(
inbuf
,
bytesLeft
,
outbuf
,
len
,
samplesPerFrame
);
s_opusCurrentFilePos
+=
len
;
len
--
;
inbuf
++
;
ec_dec_init
((
uint8_t
*
)
inbuf
,
len
);
ret
=
celt_decode_with_ec
(
inbuf
,
len
,
(
int16_t
*
)
outbuf
,
samplesPerFrame
);
if
(
ret
<
0
)
goto
exit
;
// celt error
s_opusValidSamples
=
ret
;
ret
=
ERR_OPUS_NONE
;
break
;
break
;
case
1
:
// Code 1: Two Frames in the Packet, Each with Equal Compressed Size
case
1
:
// Code 1: Two Frames in the Packet, Each with Equal Compressed Size
log_e
(
"OPUS countCode 1 not supported yet"
);
vTaskDelay
(
1000
);
// todo
ret
=
opus_FramePacking_Code1
(
inbuf
,
bytesLeft
,
outbuf
,
len
,
samplesPerFrame
,
&
frameCount
);
if
(
ret
==
OPUS_CONTINUE
)
return
ret
;
break
;
break
;
case
2
:
// Code 2: Two Frames in the Packet, with Different Compressed Sizes
case
2
:
// Code 2: Two Frames in the Packet, with Different Compressed Sizes
log_e
(
"OPUS countCode 2 not supported yet"
);
vTaskDelay
(
1000
);
// todo
ret
=
opus_FramePacking_Code2
(
inbuf
,
bytesLeft
,
outbuf
,
len
,
samplesPerFrame
,
&
frameCount
);
if
(
ret
==
OPUS_CONTINUE
)
return
ret
;
break
;
break
;
case
3
:
// Code 3: A Signaled Number of Frames in the Packet
case
3
:
// Code 3: A Signaled Number of Frames in the Packet
if
(
M
==
0
){
ret
=
opus_FramePacking_Code3
(
inbuf
,
bytesLeft
,
outbuf
,
len
,
samplesPerFrame
,
&
frameCount
);
bool
v
=
((
inbuf
[
1
]
&
0x80
)
==
0x80
);
// VBR indicator
if
(
ret
==
OPUS_CONTINUE
)
return
ret
;
if
(
v
!=
0
)
{
log_e
(
"OPUS countCode 3 with VBR not supported yet"
);
vTaskDelay
(
1000
);}
// todo
bool
p
=
((
inbuf
[
1
]
&
0x40
)
==
0x40
);
// padding bit
M
=
inbuf
[
1
]
&
0x3F
;
// max framecount
// log_i("v %i, p %i, M %i", v, p, M);
*
bytesLeft
-=
2
;
s_opusCurrentFilePos
+=
2
;
len
-=
2
;
inbuf
+=
2
;
if
(
p
){
paddingBytes
=
0
;
paddingLength
=
1
;
int
i
=
0
;
while
(
inbuf
[
i
]
==
255
){
paddingBytes
+=
inbuf
[
i
];
i
++
;
}
paddingBytes
+=
inbuf
[
i
];
paddingLength
+=
i
;
*
bytesLeft
-=
paddingLength
;
s_opusCurrentFilePos
+=
paddingLength
;
len
-=
paddingLength
;
inbuf
+=
paddingLength
;
}
fs
=
(
len
-
paddingBytes
)
/
M
;
}
*
bytesLeft
-=
fs
;
s_opusCurrentFilePos
+=
fs
;
ec_dec_init
((
uint8_t
*
)
inbuf
,
fs
);
ret
=
celt_decode_with_ec
(
inbuf
,
fs
,
(
int16_t
*
)
outbuf
,
samplesPerFrame
);
if
(
ret
<
0
)
goto
exit
;
// celt error
s_opusValidSamples
=
ret
;
M
--
;
// log_i("M %i fs %i spf %i", M, fs, samplesPerFrame);
ret
=
ERR_OPUS_NONE
;
if
(
M
==
0
)
{
s_opusCountCode
=
0
;
*
bytesLeft
-=
paddingBytes
;
paddingBytes
=
0
;
goto
exit
;}
return
ret
;
break
;
break
;
default:
default:
log_e
(
"unknown countCode %i"
,
s_opusCountCode
);
log_e
(
"unknown countCode %i"
,
s_opusCountCode
);
break
;
break
;
}
}
exit:
if
(
s_opusSegmentTableSize
==
0
){
if
(
s_opusSegmentTableSize
==
0
){
s_opusSegmentTableRdPtr
=
-
1
;
// back to the parking position
s_opusSegmentTableRdPtr
=
-
1
;
// back to the parking position
s_f_opusParseOgg
=
true
;
s_f_opusParseOgg
=
true
;
}
}
return
ret
;
return
ret
;
}
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
int8_t
opus_FramePacking_Code0
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
,
int
packetLen
,
uint16_t
samplesPerFrame
){
/* Code 0: One Frame in the Packet
For code 0 packets, the TOC byte is immediately followed by N-1 bytes
of compressed data for a single frame (where N is the size of the
packet), as illustrated
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| config |s|0|0| |
+-+-+-+-+-+-+-+-+ |
| Compressed frame 1 (N-1 bytes)... :
: |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
int
ret
=
0
;
*
bytesLeft
-=
packetLen
;
s_opusCurrentFilePos
+=
packetLen
;
packetLen
--
;
inbuf
++
;
ec_dec_init
((
uint8_t
*
)
inbuf
,
packetLen
);
ret
=
celt_decode_with_ec
(
inbuf
,
packetLen
,
(
int16_t
*
)
outbuf
,
samplesPerFrame
);
if
(
ret
<
0
)
return
ret
;
s_opusValidSamples
=
ret
;
return
ERR_OPUS_NONE
;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
int8_t
opus_FramePacking_Code1
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
,
int
packetLen
,
uint16_t
samplesPerFrame
,
uint8_t
*
frameCount
){
/* Code 1: Two Frames in the Packet, Each with Equal Compressed Size
For code 1 packets, the TOC byte is immediately followed by the (N-1)/2 bytes [where N is the size of the packet] of compressed
data for the first frame, followed by (N-1)/2 bytes of compressed data for the second frame, as illustrated. The number of payload bytes
available for compressed data, N-1, MUST be even for all code 1 packets.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| config |s|0|1| |
+-+-+-+-+-+-+-+-+ :
| Compressed frame 1 ((N-1)/2 bytes)... |
: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ :
| Compressed frame 2 ((N-1)/2 bytes)... |
: +-+-+-+-+-+-+-+-+
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
int
ret
=
0
;
static
uint16_t
c1fs
=
0
;
if
(
*
frameCount
==
0
){
packetLen
--
;
inbuf
++
;
*
bytesLeft
-=
1
;
s_opusCurrentFilePos
+=
1
;
c1fs
=
packetLen
/
2
;
// log_w("OPUS countCode 1 len %i, c1fs %i", len, c1fs);
*
frameCount
=
2
;
}
if
(
*
frameCount
>
0
){
ec_dec_init
((
uint8_t
*
)
inbuf
,
c1fs
);
ret
=
celt_decode_with_ec
(
inbuf
,
c1fs
,
(
int16_t
*
)
outbuf
,
samplesPerFrame
);
if
(
ret
<
0
)
return
ret
;
s_opusValidSamples
=
ret
;
*
bytesLeft
-=
c1fs
;
s_opusCurrentFilePos
+=
c1fs
;
}
*
frameCount
-=
1
;
if
(
*
frameCount
>
0
)
return
OPUS_CONTINUE
;
s_opusCountCode
=
0
;
c1fs
=
0
;
return
ERR_OPUS_NONE
;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
int8_t
opus_FramePacking_Code2
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
,
int
packetLen
,
uint16_t
samplesPerFrame
,
uint8_t
*
frameCount
){
/* Code 2: Two Frames in the Packet, with Different Compressed Sizes
For code 2 packets, the TOC byte is followed by a one- or two-byte sequence indicating the length of the first frame (marked N1 in the Figure),
followed by N1 bytes of compressed data for the first frame. The remaining N-N1-2 or N-N1-3 bytes are the compressed data for the second frame.
This is illustrated in the Figure. A code 2 packet MUST contain enough bytes to represent a valid length. For example, a 1-byte code 2 packet
is always invalid, and a 2-byte code 2 packet whose second byte is in the range 252...255 is also invalid. The length of the first frame, N1,
MUST also be no larger than the size of the payload remaining after decoding that length for all code 2 packets. This makes, for example,
a 2-byte code 2 packet with a second byte in the range 1...251 invalid as well (the only valid 2-byte code 2 packet is one where the length of
both frames is zero).
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| config |s|1|0| N1 (1-2 bytes): |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ :
| Compressed frame 1 (N1 bytes)... |
: +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
| Compressed frame 2... :
: |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
// log_w("OPUS countCode 2 packetLen %i", packetLen); // todo
int
ret
=
0
;
static
uint16_t
firstFrameLength
=
0
;
static
uint16_t
secondFrameLength
=
0
;
if
(
*
frameCount
==
0
){
uint8_t
b1
=
inbuf
[
1
];
uint8_t
b2
=
inbuf
[
2
];
if
(
b1
<
255
){
packetLen
-=
2
;
*
bytesLeft
-=
2
;
s_opusCurrentFilePos
+=
2
;
inbuf
+=
2
;
firstFrameLength
=
b1
;
}
else
{
packetLen
-=
3
;
*
bytesLeft
-=
3
;
s_opusCurrentFilePos
+=
3
;
inbuf
+=
3
;
firstFrameLength
=
b1
+
b2
;
}
secondFrameLength
=
packetLen
-
firstFrameLength
;
*
frameCount
=
2
;
}
if
(
*
frameCount
==
2
){
ec_dec_init
((
uint8_t
*
)
inbuf
,
firstFrameLength
);
ret
=
celt_decode_with_ec
(
inbuf
,
firstFrameLength
,
(
int16_t
*
)
outbuf
,
samplesPerFrame
);
if
(
ret
<
0
)
return
ret
;
s_opusValidSamples
=
ret
;
*
bytesLeft
-=
firstFrameLength
;
s_opusCurrentFilePos
+=
firstFrameLength
;
}
if
(
*
frameCount
==
1
){
ec_dec_init
((
uint8_t
*
)
inbuf
,
secondFrameLength
);
ret
=
celt_decode_with_ec
(
inbuf
,
secondFrameLength
,
(
int16_t
*
)
outbuf
,
samplesPerFrame
);
if
(
ret
<
0
)
return
ret
;
s_opusValidSamples
=
ret
;
*
bytesLeft
-=
secondFrameLength
;
s_opusCurrentFilePos
+=
secondFrameLength
;
}
*
frameCount
-=
1
;
if
(
*
frameCount
>
0
)
return
OPUS_CONTINUE
;
s_opusCountCode
=
0
;
firstFrameLength
=
0
;
secondFrameLength
=
0
;
return
ERR_OPUS_NONE
;
}
//----------------------------------------------------------------------------------------------------------------------------------------------------
int8_t
opus_FramePacking_Code3
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
,
int
packetLen
,
uint16_t
samplesPerFrame
,
uint8_t
*
frameCount
){
/* Code 3: A Signaled Number of Frames in the Packet
Code 3 packets signal the number of frames, as well as additional padding, called "Opus padding" to indicate that this padding is added
at the Opus layer rather than at the transport layer. Code 3 packets MUST have at least 2 bytes [R6,R7]. The TOC byte is followed by a
byte encoding the number of frames in the packet in bits 2 to 7 (marked "M" in the Figure ) 0
0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|v|p| M |
+-+-+-+-+-+-+-+-+
with bit 1 indicating whether or not Opus
padding is inserted (marked "p" in Figure 5), and bit 0 indicating VBR (marked "v" in Figure). M MUST NOT be zero, and the audio
duration contained within a packet MUST NOT exceed 120 ms. This limits the maximum frame count for any frame size to 48 (for 2.5 ms
frames), with lower limits for longer frame sizes. The Figure below illustrates the layout of the frame count byte.
When Opus padding is used, the number of bytes of padding is encoded in the bytes following the frame count byte. Values from 0...254
indicate that 0...254 bytes of padding are included, in addition to the byte(s) used to indicate the size of the padding. If the value
is 255, then the size of the additional padding is 254 bytes, plus the padding value encoded in the next byte. There MUST be at least
one more byte in the packet in this case [R6,R7]. The additional padding bytes appear at the end of the packet and MUST be set to zero
by the encoder to avoid creating a covert channel. The decoder MUST accept any value for the padding bytes, however.
Although this encoding provides multiple ways to indicate a given number of padding bytes, each uses a different number of bytes to
indicate the padding size and thus will increase the total packet size by a different amount. For example, to add 255 bytes to a
packet, set the padding bit, p, to 1, insert a single byte after the frame count byte with a value of 254, and append 254 padding bytes
with the value zero to the end of the packet. To add 256 bytes to a packet, set the padding bit to 1, insert two bytes after the frame
count byte with the values 255 and 0, respectively, and append 254 padding bytes with the value zero to the end of the packet. By using
the value 255 multiple times, it is possible to create a packet of any specific, desired size. Let P be the number of header bytes used
to indicate the padding size plus the number of padding bytes themselves (i.e., P is the total number of bytes added to the
packet). Then, P MUST be no more than N-2. In the CBR case, let R=N-2-P be the number of bytes remaining in the packet after subtracting the
(optional) padding. Then, the compressed length of each frame in bytes is equal to R/M. The value R MUST be a non-negative integer multiple
of M. The compressed data for all M frames follows, each of size R/M bytes, as illustrated in the Figure below.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| config |s|1|1|0|p| M | Padding length (Optional) :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
: Compressed frame 1 (R/M bytes)... :
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
: Compressed frame 2 (R/M bytes)... :
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
: ... :
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
: Compressed frame M (R/M bytes)... :
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Opus Padding (Optional)... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
In the VBR case, the (optional) padding length is followed by M-1 frame lengths (indicated by "N1" to "N[M-1]" in Figure 7), each encoded in a
one- or two-byte sequence as described above. The packet MUST contain enough data for the M-1 lengths after removing the (optional) padding,
and the sum of these lengths MUST be no larger than the number of bytes remaining in the packet after decoding them. The compressed data for
all M frames follows, each frame consisting of the indicated number of bytes, with the final frame consuming any remaining bytes before the final
padding, as illustrated in the Figure below. The number of header bytes (TOC byte, frame count byte, padding length bytes, and frame length bytes),
plus the signaled length of the first M-1 frames themselves, plus the signaled length of the padding MUST be no larger than N, the total
size of the packet.
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| config |s|1|1|1|p| M | Padding length (Optional) :
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: N1 (1-2 bytes): N2 (1-2 bytes): ... : N[M-1] |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
: Compressed frame 1 (N1 bytes)... :
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
: Compressed frame 2 (N2 bytes)... :
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
: ... :
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| |
: Compressed frame M... :
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
: Opus Padding (Optional)... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static
uint16_t
paddingBytes
=
0
;
static
uint16_t
fs
=
0
;
int
ret
=
0
;
uint8_t
paddingLength
=
0
;
if
(
*
frameCount
==
0
){
// log_i("code3 v %i", inbuf[1] & 0x80);
bool
v
=
((
inbuf
[
1
]
&
0x80
)
==
0x80
);
// VBR indicator
if
(
v
!=
0
)
{
log_e
(
"OPUS countCode 3 with VBR not supported yet"
);
vTaskDelay
(
1000
);}
// todo
bool
p
=
((
inbuf
[
1
]
&
0x40
)
==
0x40
);
// padding bit
*
frameCount
=
inbuf
[
1
]
&
0x3F
;
// max framecount
*
bytesLeft
-=
2
;
s_opusCurrentFilePos
+=
2
;
packetLen
-=
2
;
inbuf
+=
2
;
if
(
p
){
paddingBytes
=
0
;
paddingLength
=
1
;
int
i
=
0
;
while
(
inbuf
[
i
]
==
255
){
paddingBytes
+=
inbuf
[
i
];
i
++
;
}
paddingBytes
+=
inbuf
[
i
];
paddingLength
+=
i
;
*
bytesLeft
-=
paddingLength
;
s_opusCurrentFilePos
+=
paddingLength
;
packetLen
-=
paddingLength
;
inbuf
+=
paddingLength
;
}
else
{
paddingBytes
=
0
;
}
fs
=
(
packetLen
-
paddingBytes
)
/
*
frameCount
;
}
*
bytesLeft
-=
fs
;
s_opusCurrentFilePos
+=
fs
;
ec_dec_init
((
uint8_t
*
)
inbuf
,
fs
);
ret
=
celt_decode_with_ec
(
inbuf
,
fs
,
(
int16_t
*
)
outbuf
,
samplesPerFrame
);
if
(
ret
<
0
)
return
ret
;
// celt error
s_opusValidSamples
=
ret
;
*
frameCount
-=
1
;
if
(
*
frameCount
>
0
)
return
OPUS_CONTINUE
;
s_opusCountCode
=
0
;
*
bytesLeft
-=
paddingBytes
;
s_opusCurrentFilePos
+=
paddingBytes
;
paddingBytes
=
0
;
fs
=
0
;
return
ERR_OPUS_NONE
;
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
...
@@ -368,7 +610,7 @@ vector<uint32_t> OPUSgetMetadataBlockPicture(){
...
@@ -368,7 +610,7 @@ vector<uint32_t> OPUSgetMetadataBlockPicture(){
}
}
//----------------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
int
parseOpusTOC
(
uint8_t
TOC_Byte
){
// https://www.rfc-editor.org/rfc/rfc6716 page 16 ff
int
8_t
parseOpusTOC
(
uint8_t
TOC_Byte
){
// https://www.rfc-editor.org/rfc/rfc6716 page 16 ff
uint8_t
configNr
=
0
;
uint8_t
configNr
=
0
;
uint8_t
s
=
0
;
// stereo flag
uint8_t
s
=
0
;
// stereo flag
...
...
src/opus_decoder/opus_decoder.h
View file @
384ba4d5
...
@@ -8,7 +8,8 @@
...
@@ -8,7 +8,8 @@
#include <vector>
#include <vector>
using
namespace
std
;
using
namespace
std
;
enum
:
int8_t
{
OPUS_PARSE_OGG_DONE
=
100
,
enum
:
int8_t
{
OPUS_CONTINUE
=
110
,
OPUS_PARSE_OGG_DONE
=
100
,
ERR_OPUS_NONE
=
0
,
ERR_OPUS_NONE
=
0
,
ERR_OPUS_CHANNELS_OUT_OF_RANGE
=
-
1
,
ERR_OPUS_CHANNELS_OUT_OF_RANGE
=
-
1
,
ERR_OPUS_INVALID_SAMPLERATE
=
-
2
,
ERR_OPUS_INVALID_SAMPLERATE
=
-
2
,
...
@@ -36,6 +37,10 @@ void OPUSDecoder_FreeBuffers();
...
@@ -36,6 +37,10 @@ void OPUSDecoder_FreeBuffers();
void
OPUSDecoder_ClearBuffers
();
void
OPUSDecoder_ClearBuffers
();
void
OPUSsetDefaults
();
void
OPUSsetDefaults
();
int
OPUSDecode
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
);
int
OPUSDecode
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
);
int8_t
opus_FramePacking_Code0
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
,
int
packetLen
,
uint16_t
samplesPerFrame
);
int8_t
opus_FramePacking_Code1
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
,
int
packetLen
,
uint16_t
samplesPerFrame
,
uint8_t
*
frameCount
);
int8_t
opus_FramePacking_Code2
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
,
int
packetLen
,
uint16_t
samplesPerFrame
,
uint8_t
*
frameCount
);
int8_t
opus_FramePacking_Code3
(
uint8_t
*
inbuf
,
int
*
bytesLeft
,
short
*
outbuf
,
int
packetLen
,
uint16_t
samplesPerFrame
,
uint8_t
*
frameCount
);
uint8_t
OPUSGetChannels
();
uint8_t
OPUSGetChannels
();
uint32_t
OPUSGetSampRate
();
uint32_t
OPUSGetSampRate
();
uint8_t
OPUSGetBitsPerSample
();
uint8_t
OPUSGetBitsPerSample
();
...
@@ -47,7 +52,7 @@ int OPUSFindSyncWord(unsigned char* buf, int nBytes);
...
@@ -47,7 +52,7 @@ int OPUSFindSyncWord(unsigned char* buf, int nBytes);
int
OPUSparseOGG
(
uint8_t
*
inbuf
,
int
*
bytesLeft
);
int
OPUSparseOGG
(
uint8_t
*
inbuf
,
int
*
bytesLeft
);
int
parseOpusHead
(
uint8_t
*
inbuf
,
int
nBytes
);
int
parseOpusHead
(
uint8_t
*
inbuf
,
int
nBytes
);
int
parseOpusComment
(
uint8_t
*
inbuf
,
int
nBytes
);
int
parseOpusComment
(
uint8_t
*
inbuf
,
int
nBytes
);
int
parseOpusTOC
(
uint8_t
TOC_Byte
);
int
8_t
parseOpusTOC
(
uint8_t
TOC_Byte
);
int32_t
opus_packet_get_samples_per_frame
(
const
uint8_t
*
data
,
int32_t
Fs
);
int32_t
opus_packet_get_samples_per_frame
(
const
uint8_t
*
data
,
int32_t
Fs
);
// some helper functions
// 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