A lot of updates
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
//
|
||||
// Created by wolverindev on 28.04.19.
|
||||
//
|
||||
|
||||
#include "Converter.h"
|
||||
|
||||
using namespace tc::audio::codec;
|
||||
|
||||
Converter::Converter(size_t c, size_t s, size_t f) : _channels(c), _sample_rate(s), _frame_size(f) {}
|
||||
Converter::~Converter() {}
|
||||
|
||||
bool type::supported(value type) {
|
||||
#ifdef HAVE_CODEC_OPUS
|
||||
if(type == type::opus)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CODEC_SPEEX
|
||||
if(type == type::speex)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CODEC_FLAC
|
||||
if(type == type::flac)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CODEC_CELT
|
||||
if(type == type::celt)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#if !defined(ssize_t) && defined(WIN32)
|
||||
#define ssize_t int64_t
|
||||
#endif
|
||||
|
||||
namespace tc {
|
||||
namespace audio {
|
||||
namespace codec {
|
||||
namespace type {
|
||||
enum value {
|
||||
undefined,
|
||||
|
||||
/* supported */
|
||||
opus,
|
||||
speex,
|
||||
|
||||
/* unsupported */
|
||||
flac,
|
||||
celt
|
||||
};
|
||||
|
||||
extern bool supported(value);
|
||||
}
|
||||
|
||||
class Converter {
|
||||
public:
|
||||
Converter(size_t /* channels */, size_t /* sample rate */, size_t /* frame size */);
|
||||
virtual ~Converter();
|
||||
|
||||
/* initialize parameters depend on the codec */
|
||||
virtual bool valid() = 0;
|
||||
virtual void finalize() = 0;
|
||||
|
||||
virtual void reset_encoder() = 0;
|
||||
virtual void reset_decoder() = 0;
|
||||
|
||||
/**
|
||||
* @return number of bytes written on success
|
||||
*/
|
||||
virtual ssize_t encode(std::string& /* error */, const void* /* source */, void* /* destination */, size_t /* destination byte length */) = 0;
|
||||
|
||||
/**
|
||||
* @return number of samples on success
|
||||
*/
|
||||
virtual ssize_t decode(std::string& /* error */, const void* /* source */, size_t /* source byte length */, void* /* destination */) = 0;
|
||||
virtual ssize_t decode_lost(std::string& /* error */, size_t /* packets */) = 0;
|
||||
|
||||
virtual size_t expected_encoded_length(size_t /* sample count */) = 0;
|
||||
virtual size_t expected_decoded_length(const void* /* source */, size_t /* source byte length */) {
|
||||
return this->bytes_per_frame();
|
||||
}
|
||||
|
||||
inline size_t channels() { return this->_channels; }
|
||||
inline size_t sample_rate() { return this->_sample_rate; }
|
||||
inline size_t frame_size() { return this->_frame_size; }
|
||||
|
||||
inline size_t bytes_per_frame() { return this->_channels * this->_frame_size * 4; }
|
||||
protected:
|
||||
size_t _frame_size;
|
||||
size_t _channels;
|
||||
size_t _sample_rate;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
#include "OpusConverter.h"
|
||||
#include "../../logger.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace tc::audio::codec;
|
||||
|
||||
OpusConverter::OpusConverter(size_t c, size_t s, size_t f) : Converter(c, s, f) { }
|
||||
OpusConverter::~OpusConverter() {}
|
||||
|
||||
bool OpusConverter::valid() {
|
||||
return this->encoder && this->decoder;
|
||||
}
|
||||
|
||||
bool OpusConverter::initialize(std::string &error, int application_type) {
|
||||
lock_guard lock(this->coder_lock);
|
||||
this->_application_type = application_type;
|
||||
|
||||
if(!this->_initialize_encoder(error))
|
||||
return false;
|
||||
|
||||
if(!this->_initialize_decoder(error)) {
|
||||
this->reset_encoder();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OpusConverter::reset_encoder() {
|
||||
lock_guard lock(this->coder_lock);
|
||||
|
||||
|
||||
auto result = opus_encoder_ctl(this->encoder, OPUS_RESET_STATE);
|
||||
if(result != OPUS_OK)
|
||||
log_warn(category::audio, tr("Failed to reset opus encoder. Opus result: {}"), result);
|
||||
}
|
||||
|
||||
void OpusConverter::reset_decoder() {
|
||||
lock_guard lock(this->coder_lock);
|
||||
|
||||
auto result = opus_decoder_ctl(this->decoder, OPUS_RESET_STATE);
|
||||
if(result != OPUS_OK)
|
||||
log_warn(category::audio, tr("Failed to reset opus decoder. Opus result: {}"), result);
|
||||
}
|
||||
|
||||
|
||||
void OpusConverter::finalize() {
|
||||
lock_guard lock(this->coder_lock);
|
||||
|
||||
if(this->encoder) opus_encoder_destroy(this->encoder);
|
||||
this->encoder = nullptr;
|
||||
|
||||
if(this->decoder) opus_decoder_destroy(this->decoder);
|
||||
this->decoder = nullptr;
|
||||
}
|
||||
|
||||
ssize_t OpusConverter::encode(std::string &error, const void *source, void *target, size_t target_length) {
|
||||
lock_guard lock(this->coder_lock);
|
||||
|
||||
auto result = opus_encode_float(this->encoder, (float*) source, (int) this->_frame_size, (uint8_t*) target, (opus_int32) target_length);
|
||||
if(result < OPUS_OK) {
|
||||
error = to_string(result) + "|" + opus_strerror(result);
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ssize_t OpusConverter::decode(std::string &error, const void *source, size_t source_length, void *target) {
|
||||
lock_guard lock(this->coder_lock);
|
||||
|
||||
auto result = opus_decode_float(this->decoder, (uint8_t*) source, (opus_int32) source_length, (float*) target, (int) this->_frame_size, 0);
|
||||
if(result < OPUS_OK) {
|
||||
error = to_string(result) + "|" + opus_strerror(result);
|
||||
return -1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ssize_t OpusConverter::decode_lost(std::string &error, size_t packets) {
|
||||
lock_guard lock(this->coder_lock);
|
||||
|
||||
auto buffer = (float*) malloc(this->_frame_size * this->_channels * sizeof(float));
|
||||
while (packets-- > 0) {
|
||||
auto result = opus_decode_float(this->decoder, nullptr, 0, buffer, (int) this->_frame_size, false);
|
||||
if(result < OPUS_OK)
|
||||
log_warn(category::audio, tr("Opus decode lost resulted in error: {}"), result);
|
||||
}
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t OpusConverter::expected_encoded_length(size_t sample_count) {
|
||||
//TODO calculate stuff
|
||||
return 512;
|
||||
}
|
||||
|
||||
bool OpusConverter::_initialize_decoder(std::string &error) {
|
||||
if(!this->_finalize_decoder(error))
|
||||
return false;
|
||||
|
||||
int error_id = 0;
|
||||
this->decoder = opus_decoder_create((opus_int32) this->_sample_rate, (int) this->_channels, &error_id);
|
||||
if(!this->encoder || error_id) {
|
||||
error = "failed to create decoder (" + to_string(error_id) + ")";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpusConverter::_initialize_encoder(std::string &error) {
|
||||
if(!this->_finalize_encoder(error))
|
||||
return false;
|
||||
|
||||
int error_id = 0;
|
||||
this->encoder = opus_encoder_create((opus_int32) this->_sample_rate, (int) this->_channels, this->_application_type, &error_id);
|
||||
if(!this->encoder || error_id) {
|
||||
error = "failed to create encoder (" + to_string(error_id) + ")";
|
||||
return false;
|
||||
}
|
||||
|
||||
error_id = opus_encoder_ctl(encoder, OPUS_SET_BITRATE(64000));
|
||||
if(error_id) {
|
||||
error = "failed to set bitrate (" + to_string(error_id) + ")";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpusConverter::_finalize_decoder(std::string &) {
|
||||
if(this->decoder) {
|
||||
opus_decoder_destroy(this->decoder);
|
||||
this->decoder = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OpusConverter::_finalize_encoder(std::string &) {
|
||||
if(this->encoder) {
|
||||
opus_encoder_destroy(this->encoder);
|
||||
this->encoder = nullptr;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "Converter.h"
|
||||
#include <opus/opus.h>
|
||||
#include <mutex>
|
||||
|
||||
namespace tc {
|
||||
namespace audio {
|
||||
namespace codec {
|
||||
class OpusConverter : public Converter {
|
||||
public:
|
||||
OpusConverter(size_t /* channels */, size_t /* sample rate */, size_t /* frame size */);
|
||||
virtual ~OpusConverter();
|
||||
|
||||
bool valid() override;
|
||||
|
||||
bool initialize(std::string& /* error */, int /* application type */);
|
||||
void finalize() override;
|
||||
|
||||
void reset_encoder() override;
|
||||
void reset_decoder() override;
|
||||
|
||||
ssize_t encode(std::string & /* error */, const void * /* source */, void * /* target */, size_t /* target size */) override;
|
||||
ssize_t decode(std::string & /* error */, const void * /* source */, size_t /* source size */, void *pVoid1) override;
|
||||
|
||||
ssize_t decode_lost(std::string &string, size_t /* packets */) override;
|
||||
|
||||
size_t expected_encoded_length(size_t size) override;
|
||||
private:
|
||||
std::mutex coder_lock;
|
||||
OpusDecoder* decoder = nullptr;
|
||||
OpusEncoder* encoder = nullptr;
|
||||
|
||||
int _application_type = 0;
|
||||
|
||||
bool _finalize_encoder(std::string& /* error */);
|
||||
bool _finalize_decoder(std::string& /* error */);
|
||||
bool _initialize_encoder(std::string& /* error */);
|
||||
bool _initialize_decoder(std::string& /* error */);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user