update cspot

This commit is contained in:
philippe44
2022-11-17 14:06:00 -08:00
parent a81d0e0513
commit 7e5f27af12
137 changed files with 6046 additions and 836 deletions

View File

@@ -0,0 +1,37 @@
// Copyright (c) Kuba Szczodrzyński 2022-1-12.
#include "AACDecoder.h"
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) {
frame.sampRateCore = (int)sampleRate;
frame.nChans = channelCount;
frame.bitsPerSample = bitDepth;
return AACSetRawBlockParams(aac, 0, &frame) == 0;
}
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;
}
outLen = frame.outputSamps * sizeof(int16_t);
return (uint8_t *)pcmData;
}

View File

@@ -0,0 +1,37 @@
// Copyright (c) Kuba Szczodrzyński 2022-1-12.
#include "ALACDecoder.h"
ALACDecoder::ALACDecoder() {
// aac = AACInitDecoder();
// pcmData = (int16_t *)malloc(AAC_MAX_NSAMPS * AAC_MAX_NCHANS * sizeof(int16_t));
}
ALACDecoder::~ALACDecoder() {
// AACFreeDecoder(aac);
// free(pcmData);
}
bool ALACDecoder::setup(uint32_t sampleRate, uint8_t channelCount, uint8_t bitDepth) {
// frame.sampRateCore = (int)sampleRate;
// frame.nChans = channelCount;
// frame.bitsPerSample = bitDepth;
// return AACSetRawBlockParams(aac, 0, &frame) == 0;
}
uint8_t *ALACDecoder::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;
// }
// outLen = frame.outputSamps * sizeof(int16_t);
// return (uint8_t *)pcmData;
}

View File

@@ -0,0 +1,71 @@
// Copyright (c) Kuba Szczodrzyński 2022-1-12.
#include "AudioCodecs.h"
#include <map>
#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(BaseContainer *container) {
return getCodec(container->codec);
}
void AudioCodecs::addCodec(AudioCodec type, const std::shared_ptr<BaseCodec> &codec) {
customCodecs[type] = codec;
}

View File

@@ -0,0 +1,13 @@
// Copyright (c) Kuba Szczodrzyński 2022-1-12.
#include "BaseCodec.h"
bool BaseCodec::setup(BaseContainer *container) {
return this->setup(container->sampleRate, container->channelCount, container->bitDepth);
}
uint8_t *BaseCodec::decode(BaseContainer *container, uint32_t &outLen) {
uint32_t len;
auto *data = container->readSample(len);
return decode(data, len, outLen);
}

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,35 @@
// Copyright (c) Kuba Szczodrzyński 2022-1-14.
#include "MP3Decoder.h"
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;
}
uint8_t *MP3Decoder::decode(uint8_t *inData, uint32_t inLen, uint32_t &outLen) {
if (!inData)
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;
}
outLen = frame.outputSamps * sizeof(int16_t);
return (uint8_t *)pcmData;
}

View File

@@ -0,0 +1,46 @@
// Copyright (c) Kuba Szczodrzyński 2022-1-14.
#include "OPUSDecoder.h"
#include "opus.h"
#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);
return (uint8_t *)pcmData;
}

View File

@@ -0,0 +1,120 @@
// Copyright (c) Kuba Szczodrzyński 2022-1-14.
#include "VorbisDecoder.h"
#include "AudioCodecs.h"
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(BaseContainer *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;
}
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;
}
}
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);
}