move to new cspot

This commit is contained in:
philippe44
2023-03-25 16:48:41 -07:00
parent c712b78931
commit 008c36facf
2983 changed files with 465270 additions and 13569 deletions

View File

@@ -0,0 +1,50 @@
#include "AACDecoder.h"
#include <iostream>
using namespace bell;
AACDecoder::AACDecoder() {
aac = AACInitDecoder();
pcmData = (int16_t*)malloc(AAC_MAX_NSAMPS * AAC_MAX_NCHANS * sizeof(int16_t));
}
AACDecoder::~AACDecoder() {
AACFreeDecoder(aac);
free(pcmData);
}
bool AACDecoder::setup(uint32_t sampleRate, uint8_t channelCount,
uint8_t bitDepth) {
return true;
}
bool AACDecoder::setup(AudioContainer* container) {
return true;
}
uint8_t* AACDecoder::decode(uint8_t* inData, uint32_t& inLen,
uint32_t& outLen) {
if (!inData)
return nullptr;
int status = AACDecode(aac, static_cast<unsigned char**>(&inData),
reinterpret_cast<int*>(&inLen),
static_cast<short*>(this->pcmData));
AACGetLastFrameInfo(aac, &frame);
if (status != ERR_AAC_NONE) {
lastErrno = status;
return nullptr;
}
if (sampleRate != frame.sampRateOut) {
this->sampleRate = frame.sampRateOut;
}
if (channelCount != frame.nChans) {
this->channelCount = frame.nChans;
}
outLen = frame.outputSamps * sizeof(int16_t);
return (uint8_t*)pcmData;
}

View File

@@ -0,0 +1,77 @@
#include "AudioCodecs.h"
#include <cstring>
#include <iostream>
#include <map>
using namespace bell;
#ifdef BELL_CODEC_AAC
#include "AACDecoder.h"
static std::shared_ptr<AACDecoder> codecAac;
#endif
#ifdef BELL_CODEC_MP3
#include "MP3Decoder.h"
static std::shared_ptr<MP3Decoder> codecMp3;
#endif
#ifdef BELL_CODEC_VORBIS
#include "VorbisDecoder.h"
static std::shared_ptr<VorbisDecoder> codecVorbis;
#endif
#ifdef BELL_CODEC_OPUS
#include "OPUSDecoder.h"
static std::shared_ptr<OPUSDecoder> codecOpus;
#endif
std::map<AudioCodec, std::shared_ptr<BaseCodec>> customCodecs;
std::shared_ptr<BaseCodec> AudioCodecs::getCodec(AudioCodec type) {
if (customCodecs.find(type) != customCodecs.end())
return customCodecs[type];
switch (type) {
#ifdef BELL_CODEC_AAC
case AudioCodec::AAC:
if (codecAac)
return codecAac;
codecAac = std::make_shared<AACDecoder>();
return codecAac;
#endif
#ifdef BELL_CODEC_MP3
case AudioCodec::MP3:
if (codecMp3)
return codecMp3;
codecMp3 = std::make_shared<MP3Decoder>();
return codecMp3;
#endif
#ifdef BELL_CODEC_VORBIS
case AudioCodec::VORBIS:
if (codecVorbis)
return codecVorbis;
codecVorbis = std::make_shared<VorbisDecoder>();
return codecVorbis;
#endif
#ifdef BELL_CODEC_OPUS
case AudioCodec::OPUS:
if (codecOpus)
return codecOpus;
codecOpus = std::make_shared<OPUSDecoder>();
return codecOpus;
#endif
default:
return nullptr;
}
}
std::shared_ptr<BaseCodec> AudioCodecs::getCodec(AudioContainer* container) {
auto codec = getCodec(container->getCodec());
if (codec != nullptr) {
codec->setup(container);
}
return codec;
}
void AudioCodecs::addCodec(AudioCodec type,
const std::shared_ptr<BaseCodec>& codec) {
customCodecs[type] = codec;
}

View File

@@ -0,0 +1,30 @@
#include "BaseCodec.h"
#include <iostream>
using namespace bell;
bool BaseCodec::setup(AudioContainer* container) {
return false;
}
uint8_t* BaseCodec::decode(AudioContainer* container, uint32_t& outLen) {
auto* data = container->readSample(lastSampleLen);
if (data == nullptr) {
outLen = 0;
return nullptr;
}
if (lastSampleLen == 0) {
outLen = 0;
return nullptr;
}
availableBytes = lastSampleLen;
auto* result = decode((uint8_t*)data, availableBytes, outLen);
if (result == nullptr) {
container->consumeBytes(1);
} else {
container->consumeBytes(lastSampleLen - availableBytes);
}
return result;
}

View File

@@ -0,0 +1,8 @@
#include "DecoderGlobals.h"
bell::DecodersInstance* bell::decodersInstance;
void bell::createDecoders()
{
bell::decodersInstance = new bell::DecodersInstance();
}

View File

@@ -0,0 +1,47 @@
#include "MP3Decoder.h"
using namespace bell;
MP3Decoder::MP3Decoder() {
mp3 = MP3InitDecoder();
pcmData =
(int16_t*)malloc(MAX_NSAMP * MAX_NGRAN * MAX_NCHAN * sizeof(int16_t));
}
MP3Decoder::~MP3Decoder() {
MP3FreeDecoder(mp3);
free(pcmData);
}
bool MP3Decoder::setup(uint32_t sampleRate, uint8_t channelCount,
uint8_t bitDepth) {
return true;
}
bool MP3Decoder::setup(AudioContainer* container) {
return true;
}
uint8_t* MP3Decoder::decode(uint8_t* inData, uint32_t& inLen,
uint32_t& outLen) {
if (!inData || inLen == 0)
return nullptr;
int status = MP3Decode(mp3, static_cast<unsigned char**>(&inData),
reinterpret_cast<int*>(&inLen),
static_cast<short*>(this->pcmData),
/* useSize */ 0);
MP3GetLastFrameInfo(mp3, &frame);
if (status != ERR_MP3_NONE) {
lastErrno = status;
return nullptr;
}
if (sampleRate != frame.samprate) {
this->sampleRate = frame.samprate;
}
if (channelCount != frame.nChans) {
this->channelCount = frame.nChans;
}
outLen = frame.outputSamps * sizeof(int16_t);
return (uint8_t*)pcmData;
}

View File

@@ -0,0 +1,45 @@
#include "OPUSDecoder.h"
#include "opus.h"
using namespace bell;
#define MAX_FRAME_SIZE 6 * 960
#define MAX_CHANNELS 2
// dummy structure, just to get access to channels
struct OpusDecoder {
int dummy1;
int dummy2;
int channels;
};
OPUSDecoder::OPUSDecoder() {
opus = nullptr;
pcmData = (int16_t*)malloc(MAX_FRAME_SIZE * MAX_CHANNELS * sizeof(int16_t));
}
OPUSDecoder::~OPUSDecoder() {
if (opus)
opus_decoder_destroy(opus);
free(pcmData);
}
bool OPUSDecoder::setup(uint32_t sampleRate, uint8_t channelCount,
uint8_t bitDepth) {
if (opus)
opus_decoder_destroy(opus);
opus = opus_decoder_create((int32_t)sampleRate, channelCount, &lastErrno);
return !lastErrno;
}
uint8_t* OPUSDecoder::decode(uint8_t* inData, uint32_t& inLen,
uint32_t& outLen) {
if (!inData)
return nullptr;
outLen =
opus_decode(opus, static_cast<unsigned char*>(inData),
static_cast<int32_t>(inLen), pcmData, MAX_FRAME_SIZE, false);
outLen *= opus->channels * sizeof(int16_t);
inLen = 0;
return (uint8_t*)pcmData;
}

View File

@@ -0,0 +1,130 @@
#include "VorbisDecoder.h"
#include "AudioCodecs.h"
using namespace bell;
extern "C" {
extern vorbis_dsp_state* vorbis_dsp_create(vorbis_info* vi);
extern void vorbis_dsp_destroy(vorbis_dsp_state* v);
extern int vorbis_dsp_restart(vorbis_dsp_state* v);
extern int vorbis_dsp_headerin(vorbis_info* vi, vorbis_comment* vc,
ogg_packet* op);
extern int vorbis_dsp_synthesis(vorbis_dsp_state* vd, ogg_packet* op,
int decodep);
extern int vorbis_dsp_pcmout(vorbis_dsp_state* v, ogg_int16_t* pcm,
int samples);
extern int vorbis_dsp_read(vorbis_dsp_state* v, int samples);
}
#define VORBIS_BUF_SAMPLES 1024
#define VORBIS_BUF_CHANNELS 2
VorbisDecoder::VorbisDecoder() {
vi = new vorbis_info;
vorbis_info_init(vi);
vc = new vorbis_comment;
vorbis_comment_init(vc);
op.packet = new ogg_reference;
op.packet->buffer = new ogg_buffer;
op.packet->buffer->refcount = 0;
op.packet->buffer->ptr.owner = nullptr;
op.packet->buffer->ptr.next = nullptr;
op.packet->begin = 0;
op.packet->next = nullptr;
op.granulepos = -1;
op.packetno = 10;
pcmData = (int16_t*)malloc(VORBIS_BUF_SAMPLES * VORBIS_BUF_CHANNELS *
sizeof(uint16_t));
}
VorbisDecoder::~VorbisDecoder() {
vorbis_info_clear(vi);
vorbis_comment_clear(vc);
if (vd)
vorbis_dsp_destroy(vd);
vd = nullptr;
free(pcmData);
}
bool VorbisDecoder::setup(AudioContainer* container) {
/*
uint32_t setupLen;
uint8_t* setup = container->getSetupData(setupLen, AudioCodec::VORBIS);
if (!setup)
return false;
op.b_o_s = true; // mark this page as beginning of stream
uint32_t bytesLeft = setupLen - 1; // minus header count length (8 bit)
std::vector<uint32_t> headers(setup[0]);
for (uint8_t i = 0; i < setup[0]; i++) {
uint8_t* sizeByte = (uint8_t*)setup + 1 + i;
headers[i] = 0;
while (*sizeByte == 255) {
headers[i] += *(sizeByte++);
bytesLeft--;
}
headers[i] += *sizeByte;
bytesLeft--;
}
// parse all headers from the setup data
for (const auto& headerSize : headers) {
setPacket(setup + setupLen - bytesLeft, headerSize);
bytesLeft -= headerSize;
lastErrno = vorbis_dsp_headerin(vi, vc, &op);
if (lastErrno < 0) {
bytesLeft = 0;
break;
}
}
// parse last header, not present in header table (seems to happen for MP4 containers)
if (bytesLeft) {
setPacket(setup + setupLen - bytesLeft, bytesLeft);
lastErrno = vorbis_dsp_headerin(vi, vc, &op);
}
// disable BOS to allow reading audio data
op.b_o_s = false;
// set up the codec
if (vd)
vorbis_dsp_restart(vd);
else
vd = vorbis_dsp_create(vi);
return !lastErrno;
*/
return false;
}
bool VorbisDecoder::setup(uint32_t sampleRate, uint8_t channelCount,
uint8_t bitDepth) {
// manual setup is not allowed
return false;
}
uint8_t* VorbisDecoder::decode(uint8_t* inData, uint32_t& inLen,
uint32_t& outLen) {
if (!inData || !vi)
return nullptr;
setPacket(inData, inLen);
// sources:
// - vorbisfile.c:556
// - vorbisfile.c:1557
lastErrno = vorbis_dsp_synthesis(vd, &op, 1);
if (lastErrno < 0)
return nullptr;
int samples = vorbis_dsp_pcmout(vd, pcmData, VORBIS_BUF_SAMPLES);
outLen = samples;
if (samples) {
if (samples > 0) {
vorbis_dsp_read(vd, samples);
outLen = samples * 2 * vi->channels;
}
}
inLen = 0;
return (uint8_t*)pcmData;
}
void VorbisDecoder::setPacket(uint8_t* inData, uint32_t inLen) const {
op.packet->buffer->data = static_cast<unsigned char*>(inData);
op.packet->buffer->size = static_cast<long>(inLen);
op.packet->length = static_cast<long>(inLen);
}

View File

@@ -0,0 +1,22 @@
#pragma once
#include "BaseCodec.h"
#include "aacdec.h"
namespace bell {
class AACDecoder : public BaseCodec {
private:
HAACDecoder aac;
int16_t* pcmData;
AACFrameInfo frame = {};
public:
AACDecoder();
~AACDecoder();
bool setup(uint32_t sampleRate, uint8_t channelCount,
uint8_t bitDepth) override;
bool setup(AudioContainer* container) override;
uint8_t* decode(uint8_t* inData, uint32_t& inLen, uint32_t& outLen) override;
};
} // namespace bell

View File

@@ -0,0 +1,16 @@
#pragma once
#include <memory>
#include "BaseCodec.h"
#include "AudioContainer.h"
namespace bell {
class AudioCodecs {
public:
static std::shared_ptr<BaseCodec> getCodec(AudioCodec type);
static std::shared_ptr<BaseCodec> getCodec(AudioContainer* container);
static void addCodec(AudioCodec type,
const std::shared_ptr<BaseCodec>& codec);
};
} // namespace bell

View File

@@ -0,0 +1,49 @@
#pragma once
#include "AudioContainer.h"
namespace bell {
class BaseCodec {
private:
uint32_t lastSampleLen, availableBytes;
public:
uint32_t sampleRate = 44100;
uint8_t channelCount = 2;
uint8_t bitDepth = 16;
/**
* Setup the codec (sample rate, channel count, etc) using the specified container.
*/
virtual bool setup(AudioContainer* container);
/**
* Setup the codec manually, using the provided values.
*/
virtual bool setup(uint32_t sampleRate, uint8_t channelCount,
uint8_t bitDepth) = 0;
/**
* Decode the given sample.
*
* @param [in] inData encoded data. Should allow nullptr, in which case nullptr should be returned.
* @param [in] inLen size of inData, in bytes
* @param [out] outLen size of output PCM data, in bytes
* @return pointer to decoded raw PCM audio data, allocated inside the codec object; nullptr on failure
*/
virtual uint8_t* decode(uint8_t* inData, uint32_t& inLen,
uint32_t& outLen) = 0;
/**
* Read a single sample from the container, decode it, and return the result.
*
* @param [in] container media container to read the sample from (the container's codec must match this instance)
* @param [out] outLen size of output PCM data, in bytes
* @return pointer to decoded raw PCM audio data, allocated inside the codec object; nullptr on failure
*/
uint8_t* decode(AudioContainer* container, uint32_t& outLen);
/**
* Last error that occurred, this is a codec-specific value.
* This may be set by a codec upon decoding failure.
*/
int lastErrno = -1;
};
} // namespace bell

View File

@@ -0,0 +1,13 @@
#pragma once
namespace bell {
enum class AudioCodec {
UNKNOWN = 0,
AAC = 1,
MP3 = 2,
VORBIS = 3,
OPUS = 4,
FLAC = 5,
};
}

View File

@@ -0,0 +1,52 @@
#ifndef BELL_DISABLE_CODECS
#ifndef DECODER_GLOBALS_H
#define DECODER_GLOBALS_H
#define AAC_READBUF_SIZE (4 * AAC_MAINBUF_SIZE * AAC_MAX_NCHANS)
#define MP3_READBUF_SIZE (2 * 1024);
#include <stdio.h>
#include <stdlib.h>
#include <memory>
#include "aacdec.h"
#include "mp3dec.h"
namespace bell
{
class DecodersInstance
{
public:
DecodersInstance(){};
~DecodersInstance()
{
MP3FreeDecoder(mp3Decoder);
AACFreeDecoder(aacDecoder);
};
HAACDecoder aacDecoder = NULL;
HMP3Decoder mp3Decoder = NULL;
void ensureAAC()
{
if (aacDecoder == NULL)
{
aacDecoder = AACInitDecoder();
}
}
void ensureMP3()
{
if (mp3Decoder == NULL)
{
mp3Decoder = MP3InitDecoder();
}
}
};
extern bell::DecodersInstance* decodersInstance;
void createDecoders();
}
#endif
#endif

View File

@@ -0,0 +1,22 @@
#pragma once
#include "BaseCodec.h"
#include "mp3dec.h"
namespace bell {
class MP3Decoder : public BaseCodec {
private:
HMP3Decoder mp3;
int16_t* pcmData;
MP3FrameInfo frame = {};
public:
MP3Decoder();
~MP3Decoder();
bool setup(uint32_t sampleRate, uint8_t channelCount,
uint8_t bitDepth) override;
bool setup(AudioContainer* container) override;
uint8_t* decode(uint8_t* inData, uint32_t& inLen, uint32_t& outLen) override;
};
} // namespace bell

View File

@@ -0,0 +1,20 @@
#pragma once
#include "BaseCodec.h"
struct OpusDecoder;
namespace bell {
class OPUSDecoder : public BaseCodec {
private:
OpusDecoder* opus;
int16_t* pcmData;
public:
OPUSDecoder();
~OPUSDecoder();
bool setup(uint32_t sampleRate, uint8_t channelCount,
uint8_t bitDepth) override;
uint8_t* decode(uint8_t* inData, uint32_t& inLen, uint32_t& outLen) override;
};
} // namespace bell

View File

@@ -0,0 +1,26 @@
#pragma once
#include "BaseCodec.h"
#include "ivorbiscodec.h"
namespace bell {
class VorbisDecoder : public BaseCodec {
private:
vorbis_info* vi = nullptr;
vorbis_comment* vc = nullptr;
vorbis_dsp_state* vd = nullptr;
ogg_packet op = {};
int16_t* pcmData;
public:
VorbisDecoder();
~VorbisDecoder();
bool setup(uint32_t sampleRate, uint8_t channelCount,
uint8_t bitDepth) override;
uint8_t* decode(uint8_t* inData, uint32_t& inLen, uint32_t& outLen) override;
bool setup(AudioContainer* container) override;
private:
void setPacket(uint8_t* inData, uint32_t inLen) const;
};
} // namespace bell