aboutsummaryrefslogtreecommitdiff
path: root/include/lc3_cpp.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/lc3_cpp.h')
-rw-r--r--include/lc3_cpp.h143
1 files changed, 85 insertions, 58 deletions
diff --git a/include/lc3_cpp.h b/include/lc3_cpp.h
index acd3d0b..1949eb9 100644
--- a/include/lc3_cpp.h
+++ b/include/lc3_cpp.h
@@ -50,11 +50,12 @@ enum class PcmFormat {
template <typename T>
class Base {
protected:
- Base(int dt_us, int sr_hz, int sr_pcm_hz, size_t nchannels)
+ Base(int dt_us, int sr_hz, int sr_pcm_hz, size_t nchannels, bool hrmode)
: dt_us_(dt_us),
sr_hz_(sr_hz),
sr_pcm_hz_(sr_pcm_hz == 0 ? sr_hz : sr_pcm_hz),
- nchannels_(nchannels) {
+ nchannels_(nchannels),
+ hrmode_(hrmode) {
states.reserve(nchannels_);
}
@@ -63,37 +64,50 @@ class Base {
int dt_us_, sr_hz_;
int sr_pcm_hz_;
size_t nchannels_;
+ bool hrmode_;
using state_ptr = std::unique_ptr<T, decltype(&free)>;
std::vector<state_ptr> states;
public:
// Return the number of PCM samples in a frame
- int GetFrameSamples() { return lc3_frame_samples(dt_us_, sr_pcm_hz_); }
+ int GetFrameSamples() {
+ return lc3_hr_frame_samples(hrmode_, dt_us_, sr_pcm_hz_); }
- // Return the size of frames, from bitrate
- int GetFrameBytes(int bitrate) { return lc3_frame_bytes(dt_us_, bitrate); }
+ // Return the size of a frame block, from bitrate
+ int GetFrameBytes(int bitrate) {
+ return lc3_hr_frame_block_bytes(
+ hrmode_, dt_us_, sr_hz_, nchannels_, bitrate); }
- // Resolve the bitrate, from the size of frames
- int ResolveBitrate(int nbytes) { return lc3_resolve_bitrate(dt_us_, nbytes); }
+ // Resolve the bitrate, from the size of frame blocks
+ int ResolveBitrate(int nbytes) {
+ return lc3_hr_resolve_bitrate(hrmode_, dt_us_, sr_hz_, nbytes); }
// Return algorithmic delay, as a number of samples
- int GetDelaySamples() { return lc3_delay_samples(dt_us_, sr_pcm_hz_); }
+ int GetDelaySamples() {
+ return lc3_hr_delay_samples(hrmode_, dt_us_, sr_pcm_hz_); }
}; // class Base
// Encoder Class
class Encoder : public Base<struct lc3_encoder> {
template <typename T>
- int EncodeImpl(PcmFormat fmt, const T *pcm, int frame_size, uint8_t *out) {
+ int EncodeImpl(PcmFormat fmt, const T *pcm, int block_size, uint8_t *out) {
if (states.size() != nchannels_) return -1;
enum lc3_pcm_format cfmt = static_cast<lc3_pcm_format>(fmt);
int ret = 0;
- for (size_t ich = 0; ich < nchannels_; ich++)
+ uint8_t *out_ptr = out;
+ for (size_t ich = 0; ich < nchannels_; ich++) {
+ int frame_size = block_size / nchannels_
+ + (ich < block_size % nchannels_);
+
ret |= lc3_encode(states[ich].get(), cfmt, pcm + ich, nchannels_,
- frame_size, out + ich * frame_size);
+ frame_size, out_ptr);
+
+ out_ptr += frame_size;
+ }
return ret;
}
@@ -101,21 +115,24 @@ class Encoder : public Base<struct lc3_encoder> {
public:
// Encoder construction / destruction
//
- // The frame duration `dt_us` is 7500 or 10000 us.
- // The samplerate `sr_hz` is 8000, 16000, 24000, 32000 or 48000 Hz.
+ // The frame duration `dt_us` is 2500, 5000, 7500 or 10000 us.
+ // The sample rate `sr_hz` is 8000, 16000, 24000, 32000 or 48000 Hz.
+ // The `hrmode` flag enables the high-resolution mode, in which case
+ // the sample rate is 48000 or 96000 Hz.
//
// The `sr_pcm_hz` parameter is a downsampling option of PCM input,
- // the value 0 fallback to the samplerate of the encoded stream `sr_hz`.
+ // the value 0 fallback to the sample rate of the encoded stream `sr_hz`.
// When used, `sr_pcm_hz` is intended to be higher or equal to the encoder
- // samplerate `sr_hz`.
+ // sample rate `sr_hz`.
- Encoder(int dt_us, int sr_hz, int sr_pcm_hz = 0, size_t nchannels = 1)
- : Base(dt_us, sr_hz, sr_pcm_hz, nchannels) {
+ Encoder(int dt_us, int sr_hz, int sr_pcm_hz = 0,
+ size_t nchannels = 1, bool hrmode = false)
+ : Base(dt_us, sr_hz, sr_pcm_hz, nchannels, hrmode) {
for (size_t ich = 0; ich < nchannels_; ich++) {
- auto s = state_ptr(
- (lc3_encoder_t)malloc(lc3_encoder_size(dt_us_, sr_pcm_hz_)), free);
+ auto s = state_ptr((lc3_encoder_t)
+ malloc(lc3_hr_encoder_size(hrmode_, dt_us_, sr_pcm_hz_)), free);
- if (lc3_setup_encoder(dt_us_, sr_hz_, sr_pcm_hz_, s.get()))
+ if (lc3_hr_setup_encoder(hrmode_, dt_us_, sr_hz_, sr_pcm_hz_, s.get()))
states.push_back(std::move(s));
}
}
@@ -126,7 +143,7 @@ class Encoder : public Base<struct lc3_encoder> {
void Reset() {
for (auto &s : states)
- lc3_setup_encoder(dt_us_, sr_hz_, sr_pcm_hz_, s.get());
+ lc3_hr_setup_encoder(hrmode_, dt_us_, sr_hz_, sr_pcm_hz_, s.get());
}
// Encode
@@ -135,43 +152,43 @@ class Encoder : public Base<struct lc3_encoder> {
// according the type of `pcm` input buffer, or by selecting a format.
//
// The PCM samples are read in interleaved way, and consecutive
- // `nchannels` frames of size `frame_size` are output in `out` buffer.
+ // `nchannels` frames, are output in `out` buffer, of size `buffer_size`.
//
// The value returned is 0 on successs, -1 otherwise.
- int Encode(const int16_t *pcm, int frame_size, uint8_t *out) {
- return EncodeImpl(PcmFormat::kS16, pcm, frame_size, out);
+ int Encode(const int16_t *pcm, int block_size, uint8_t *out) {
+ return EncodeImpl(PcmFormat::kS16, pcm, block_size, out);
}
- int Encode(const int32_t *pcm, int frame_size, uint8_t *out) {
- return EncodeImpl(PcmFormat::kS24, pcm, frame_size, out);
+ int Encode(const int32_t *pcm, int block_size, uint8_t *out) {
+ return EncodeImpl(PcmFormat::kS24, pcm, block_size, out);
}
- int Encode(const float *pcm, int frame_size, uint8_t *out) {
- return EncodeImpl(PcmFormat::kF32, pcm, frame_size, out);
+ int Encode(const float *pcm, int block_size, uint8_t *out) {
+ return EncodeImpl(PcmFormat::kF32, pcm, block_size, out);
}
- int Encode(PcmFormat fmt, const void *pcm, int frame_size, uint8_t *out) {
+ int Encode(PcmFormat fmt, const void *pcm, int block_size, uint8_t *out) {
uintptr_t pcm_ptr = reinterpret_cast<uintptr_t>(pcm);
switch (fmt) {
case PcmFormat::kS16:
assert(pcm_ptr % alignof(int16_t) == 0);
return EncodeImpl(fmt, reinterpret_cast<const int16_t *>(pcm),
- frame_size, out);
+ block_size, out);
case PcmFormat::kS24:
assert(pcm_ptr % alignof(int32_t) == 0);
return EncodeImpl(fmt, reinterpret_cast<const int32_t *>(pcm),
- frame_size, out);
+ block_size, out);
case PcmFormat::kS24In3Le:
return EncodeImpl(fmt, reinterpret_cast<const int8_t(*)[3]>(pcm),
- frame_size, out);
+ block_size, out);
case PcmFormat::kF32:
assert(pcm_ptr % alignof(float) == 0);
- return EncodeImpl(fmt, reinterpret_cast<const float *>(pcm), frame_size,
+ return EncodeImpl(fmt, reinterpret_cast<const float *>(pcm), block_size,
out);
}
@@ -183,37 +200,47 @@ class Encoder : public Base<struct lc3_encoder> {
// Decoder Class
class Decoder : public Base<struct lc3_decoder> {
template <typename T>
- int DecodeImpl(const uint8_t *in, int frame_size, PcmFormat fmt, T *pcm) {
+ int DecodeImpl(const uint8_t *in, int block_size, PcmFormat fmt, T *pcm) {
if (states.size() != nchannels_) return -1;
enum lc3_pcm_format cfmt = static_cast<enum lc3_pcm_format>(fmt);
int ret = 0;
- for (size_t ich = 0; ich < nchannels_; ich++)
- ret |= lc3_decode(states[ich].get(), in + ich * frame_size, frame_size,
+ const uint8_t *in_ptr = in;
+ for (size_t ich = 0; ich < nchannels_; ich++) {
+ int frame_size = block_size / nchannels_
+ + (ich < block_size % nchannels_);
+
+ ret |= lc3_decode(states[ich].get(), in_ptr, frame_size,
cfmt, pcm + ich, nchannels_);
+ in_ptr += frame_size;
+ }
+
return ret;
}
public:
// Decoder construction / destruction
//
- // The frame duration `dt_us` is 7500 or 10000 us.
- // The samplerate `sr_hz` is 8000, 16000, 24000, 32000 or 48000 Hz.
+ // The frame duration `dt_us` is 2500, 5000, 7500 or 10000 us.
+ // The sample rate `sr_hz` is 8000, 16000, 24000, 32000 or 48000 Hz.
+ // The `hrmode` flag enables the high-resolution mode, in which case
+ // the sample rate is 48000 or 96000 Hz.
//
// The `sr_pcm_hz` parameter is an downsampling option of PCM output,
- // the value 0 fallback to the samplerate of the decoded stream `sr_hz`.
+ // the value 0 fallback to the sample rate of the decoded stream `sr_hz`.
// When used, `sr_pcm_hz` is intended to be higher or equal to the decoder
- // samplerate `sr_hz`.
+ // sample rate `sr_hz`.
- Decoder(int dt_us, int sr_hz, int sr_pcm_hz = 0, size_t nchannels = 1)
- : Base(dt_us, sr_hz, sr_pcm_hz, nchannels) {
+ Decoder(int dt_us, int sr_hz, int sr_pcm_hz = 0,
+ size_t nchannels = 1, bool hrmode = false)
+ : Base(dt_us, sr_hz, sr_pcm_hz, nchannels, hrmode) {
for (size_t i = 0; i < nchannels_; i++) {
- auto s = state_ptr(
- (lc3_decoder_t)malloc(lc3_decoder_size(dt_us_, sr_pcm_hz_)), free);
+ auto s = state_ptr((lc3_decoder_t)
+ malloc(lc3_hr_decoder_size(hrmode_, dt_us_, sr_pcm_hz_)), free);
- if (lc3_setup_decoder(dt_us_, sr_hz_, sr_pcm_hz_, s.get()))
+ if (lc3_hr_setup_decoder(hrmode_, dt_us_, sr_hz_, sr_pcm_hz_, s.get()))
states.push_back(std::move(s));
}
}
@@ -224,12 +251,12 @@ class Decoder : public Base<struct lc3_decoder> {
void Reset() {
for (auto &s : states)
- lc3_setup_decoder(dt_us_, sr_hz_, sr_pcm_hz_, s.get());
+ lc3_hr_setup_decoder(hrmode_, dt_us_, sr_hz_, sr_pcm_hz_, s.get());
}
// Decode
//
- // Consecutive `nchannels` frames of size `frame_size` are decoded
+ // Decode a frame block of size `block_size`,
// in the `pcm` buffer in interleaved way.
//
// The PCM samples are output in signed 16 bits, 24 bits, float,
@@ -238,39 +265,39 @@ class Decoder : public Base<struct lc3_decoder> {
// The value returned is 0 on successs, 1 when PLC has been performed,
// and -1 otherwise.
- int Decode(const uint8_t *in, int frame_size, int16_t *pcm) {
- return DecodeImpl(in, frame_size, PcmFormat::kS16, pcm);
+ int Decode(const uint8_t *in, int block_size, int16_t *pcm) {
+ return DecodeImpl(in, block_size, PcmFormat::kS16, pcm);
}
- int Decode(const uint8_t *in, int frame_size, int32_t *pcm) {
- return DecodeImpl(in, frame_size, PcmFormat::kS24In3Le, pcm);
+ int Decode(const uint8_t *in, int block_size, int32_t *pcm) {
+ return DecodeImpl(in, block_size, PcmFormat::kS24In3Le, pcm);
}
- int Decode(const uint8_t *in, int frame_size, float *pcm) {
- return DecodeImpl(in, frame_size, PcmFormat::kF32, pcm);
+ int Decode(const uint8_t *in, int block_size, float *pcm) {
+ return DecodeImpl(in, block_size, PcmFormat::kF32, pcm);
}
- int Decode(const uint8_t *in, int frame_size, PcmFormat fmt, void *pcm) {
+ int Decode(const uint8_t *in, int block_size, PcmFormat fmt, void *pcm) {
uintptr_t pcm_ptr = reinterpret_cast<uintptr_t>(pcm);
switch (fmt) {
case PcmFormat::kS16:
assert(pcm_ptr % alignof(int16_t) == 0);
- return DecodeImpl(in, frame_size, fmt,
+ return DecodeImpl(in, block_size, fmt,
reinterpret_cast<int16_t *>(pcm));
case PcmFormat::kS24:
assert(pcm_ptr % alignof(int32_t) == 0);
- return DecodeImpl(in, frame_size, fmt,
+ return DecodeImpl(in, block_size, fmt,
reinterpret_cast<int32_t *>(pcm));
case PcmFormat::kS24In3Le:
- return DecodeImpl(in, frame_size, fmt,
+ return DecodeImpl(in, block_size, fmt,
reinterpret_cast<int8_t(*)[3]>(pcm));
case PcmFormat::kF32:
assert(pcm_ptr % alignof(float) == 0);
- return DecodeImpl(in, frame_size, fmt, reinterpret_cast<float *>(pcm));
+ return DecodeImpl(in, block_size, fmt, reinterpret_cast<float *>(pcm));
}
return -1;