mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2026-05-20 20:25:32 +01:00
applied platformio structure
This commit is contained in:
112
lib/spotify/cspot/bell/main/audio-codec/AACDecoder.cpp
Normal file
112
lib/spotify/cspot/bell/main/audio-codec/AACDecoder.cpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "AACDecoder.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h> // for free, malloc
|
||||
#include <string.h>
|
||||
#include "e_tmp4audioobjecttype.h"
|
||||
#include "pvmp4audiodecoder_api.h"
|
||||
|
||||
namespace bell {
|
||||
class AudioContainer;
|
||||
} // namespace bell
|
||||
|
||||
using namespace bell;
|
||||
|
||||
AACDecoder::AACDecoder() {
|
||||
aacDecoder =
|
||||
(tPVMP4AudioDecoderExternal*)malloc(sizeof(tPVMP4AudioDecoderExternal));
|
||||
|
||||
int32_t pMemRequirement = PVMP4AudioDecoderGetMemRequirements();
|
||||
pMem = malloc(pMemRequirement);
|
||||
memset(aacDecoder, 0, sizeof(tPVMP4AudioDecoderExternal));
|
||||
memset(pMem, 0, pMemRequirement);
|
||||
|
||||
// Initialize the decoder buffers
|
||||
outputBuffer.resize(4096);
|
||||
|
||||
aacDecoder->pOutputBuffer_plus = &outputBuffer[2048];
|
||||
aacDecoder->pOutputBuffer = &outputBuffer[0];
|
||||
aacDecoder->inputBufferMaxLength = PVMP4AUDIODECODER_INBUFSIZE;
|
||||
|
||||
// Settings
|
||||
aacDecoder->desiredChannels = 2;
|
||||
aacDecoder->outputFormat = OUTPUTFORMAT_16PCM_INTERLEAVED;
|
||||
aacDecoder->aacPlusEnabled = TRUE;
|
||||
|
||||
// State
|
||||
aacDecoder->inputBufferCurrentLength = 0;
|
||||
aacDecoder->inputBufferUsedLength = 0;
|
||||
aacDecoder->remainderBits = 0;
|
||||
|
||||
firstFrame = true;
|
||||
|
||||
assert(PVMP4AudioDecoderInitLibrary(aacDecoder, pMem) == MP4AUDEC_SUCCESS);
|
||||
}
|
||||
|
||||
AACDecoder::~AACDecoder() {
|
||||
free(pMem);
|
||||
free(aacDecoder);
|
||||
}
|
||||
|
||||
int AACDecoder::getDecodedStreamType() {
|
||||
switch (aacDecoder->extendedAudioObjectType) {
|
||||
case MP4AUDIO_AAC_LC:
|
||||
case MP4AUDIO_LTP:
|
||||
return AAC;
|
||||
case MP4AUDIO_SBR:
|
||||
return AACPLUS;
|
||||
case MP4AUDIO_PS:
|
||||
return ENH_AACPLUS;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool AACDecoder::setup(uint32_t sampleRate, uint8_t channelCount,
|
||||
uint8_t bitDepth) {
|
||||
PVMP4AudioDecoderResetBuffer(pMem);
|
||||
assert(PVMP4AudioDecoderInitLibrary(aacDecoder, pMem) == MP4AUDEC_SUCCESS);
|
||||
firstFrame = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AACDecoder::setup(AudioContainer* container) {
|
||||
PVMP4AudioDecoderResetBuffer(pMem);
|
||||
assert(PVMP4AudioDecoderInitLibrary(aacDecoder, pMem) == MP4AUDEC_SUCCESS);
|
||||
firstFrame = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t* AACDecoder::decode(uint8_t* inData, uint32_t& inLen,
|
||||
uint32_t& outLen) {
|
||||
if (!inData || inLen == 0)
|
||||
return nullptr;
|
||||
|
||||
aacDecoder->inputBufferCurrentLength = inLen;
|
||||
aacDecoder->inputBufferUsedLength = 0;
|
||||
aacDecoder->inputBufferMaxLength = inLen;
|
||||
aacDecoder->pInputBuffer = inData;
|
||||
aacDecoder->remainderBits = 0;
|
||||
aacDecoder->repositionFlag = true;
|
||||
|
||||
int32_t status;
|
||||
status = PVMP4AudioDecodeFrame(aacDecoder, pMem);
|
||||
|
||||
if (status != MP4AUDEC_SUCCESS) {
|
||||
outLen = 0;
|
||||
inLen = 0;
|
||||
return nullptr;
|
||||
} else {
|
||||
inLen -= aacDecoder->inputBufferUsedLength;
|
||||
}
|
||||
|
||||
outLen = aacDecoder->frameLength * sizeof(int16_t);
|
||||
|
||||
// Handle AAC+
|
||||
if (aacDecoder->aacPlusUpsamplingFactor == 2) {
|
||||
outLen *= 2;
|
||||
}
|
||||
|
||||
outLen *= aacDecoder->desiredChannels;
|
||||
return (uint8_t*)&outputBuffer[0];
|
||||
}
|
||||
87
lib/spotify/cspot/bell/main/audio-codec/AudioCodecs.cpp
Normal file
87
lib/spotify/cspot/bell/main/audio-codec/AudioCodecs.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
#include "AudioCodecs.h"
|
||||
|
||||
#include <map> // for map, operator!=, map<>::iterator, map<>:...
|
||||
#include <type_traits> // for remove_extent_t
|
||||
|
||||
#include "AudioContainer.h" // for AudioContainer
|
||||
|
||||
namespace bell {
|
||||
class BaseCodec;
|
||||
} // namespace bell
|
||||
|
||||
using namespace bell;
|
||||
|
||||
#ifdef BELL_CODEC_AAC
|
||||
#include "AACDecoder.h" // for AACDecoder
|
||||
|
||||
static std::shared_ptr<AACDecoder> codecAac;
|
||||
#endif
|
||||
|
||||
#ifdef BELL_CODEC_MP3
|
||||
#include "MP3Decoder.h" // for MP3Decoder
|
||||
|
||||
static std::shared_ptr<MP3Decoder> codecMp3;
|
||||
#endif
|
||||
|
||||
#ifdef BELL_CODEC_VORBIS
|
||||
#include "VorbisDecoder.h" // for VorbisDecoder
|
||||
|
||||
static std::shared_ptr<VorbisDecoder> codecVorbis;
|
||||
#endif
|
||||
|
||||
#ifdef BELL_CODEC_OPUS
|
||||
#include "OPUSDecoder.h" // for OPUSDecoder
|
||||
|
||||
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;
|
||||
}
|
||||
28
lib/spotify/cspot/bell/main/audio-codec/BaseCodec.cpp
Normal file
28
lib/spotify/cspot/bell/main/audio-codec/BaseCodec.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#include "BaseCodec.h"
|
||||
|
||||
#include "AudioContainer.h" // for AudioContainer
|
||||
|
||||
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);
|
||||
container->consumeBytes(lastSampleLen - availableBytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "DecoderGlobals.h"
|
||||
|
||||
bell::DecodersInstance* bell::decodersInstance;
|
||||
|
||||
void bell::createDecoders() {
|
||||
bell::decodersInstance = new bell::DecodersInstance();
|
||||
}
|
||||
56
lib/spotify/cspot/bell/main/audio-codec/MP3Decoder.cpp
Normal file
56
lib/spotify/cspot/bell/main/audio-codec/MP3Decoder.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "MP3Decoder.h"
|
||||
|
||||
#include <stdlib.h> // for free, malloc
|
||||
#include <cstdio>
|
||||
|
||||
namespace bell {
|
||||
class AudioContainer;
|
||||
} // namespace bell
|
||||
|
||||
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;
|
||||
inLen -= 2;
|
||||
outLen = 0;
|
||||
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;
|
||||
}
|
||||
49
lib/spotify/cspot/bell/main/audio-codec/OPUSDecoder.cpp
Normal file
49
lib/spotify/cspot/bell/main/audio-codec/OPUSDecoder.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "OPUSDecoder.h"
|
||||
|
||||
#include <stdlib.h> // for free, malloc
|
||||
|
||||
#include "CodecType.h" // for bell
|
||||
#include "opus.h" // for opus_decoder_destroy, opus_decode, opus_decod...
|
||||
|
||||
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;
|
||||
}
|
||||
138
lib/spotify/cspot/bell/main/audio-codec/VorbisDecoder.cpp
Normal file
138
lib/spotify/cspot/bell/main/audio-codec/VorbisDecoder.cpp
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "VorbisDecoder.h"
|
||||
|
||||
#include <stdlib.h> // for free, malloc
|
||||
|
||||
#include "CodecType.h" // for bell
|
||||
#include "config_types.h" // for ogg_int16_t
|
||||
|
||||
namespace bell {
|
||||
class AudioContainer;
|
||||
} // namespace bell
|
||||
|
||||
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);
|
||||
}
|
||||
30
lib/spotify/cspot/bell/main/audio-codec/include/AACDecoder.h
Normal file
30
lib/spotify/cspot/bell/main/audio-codec/include/AACDecoder.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h> // for uint8_t, uint32_t, int16_t
|
||||
#include <vector>
|
||||
|
||||
#include "BaseCodec.h" // for BaseCodec
|
||||
#include "pvmp4audiodecoder_api.h" // for tPVMP4AudioDecoderExternal
|
||||
|
||||
namespace bell {
|
||||
class AudioContainer;
|
||||
|
||||
class AACDecoder : public BaseCodec {
|
||||
private:
|
||||
tPVMP4AudioDecoderExternal* aacDecoder;
|
||||
std::vector<uint8_t> inputBuffer;
|
||||
std::vector<int16_t> outputBuffer;
|
||||
void* pMem;
|
||||
bool firstFrame = true;
|
||||
|
||||
int getDecodedStreamType();
|
||||
|
||||
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
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory> // for shared_ptr
|
||||
|
||||
#include "AudioContainer.h" // for AudioContainer
|
||||
#include "BaseCodec.h" // for BaseCodec
|
||||
#include "CodecType.h" // for AudioCodec
|
||||
|
||||
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
|
||||
50
lib/spotify/cspot/bell/main/audio-codec/include/BaseCodec.h
Normal file
50
lib/spotify/cspot/bell/main/audio-codec/include/BaseCodec.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h> // for uint32_t, uint8_t
|
||||
|
||||
namespace bell {
|
||||
class AudioContainer;
|
||||
|
||||
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
|
||||
13
lib/spotify/cspot/bell/main/audio-codec/include/CodecType.h
Normal file
13
lib/spotify/cspot/bell/main/audio-codec/include/CodecType.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
namespace bell {
|
||||
enum class AudioCodec {
|
||||
UNKNOWN = 0,
|
||||
AAC = 1,
|
||||
MP3 = 2,
|
||||
VORBIS = 3,
|
||||
OPUS = 4,
|
||||
FLAC = 5,
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#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> // for NULL
|
||||
|
||||
// #include "aacdec.h" // for AACFreeDecoder, AACInitDecoder, HAACDecoder
|
||||
#include "mp3dec.h" // for MP3FreeDecoder, MP3InitDecoder, HMP3Decoder
|
||||
|
||||
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();
|
||||
} // namespace bell
|
||||
|
||||
#endif
|
||||
#endif
|
||||
26
lib/spotify/cspot/bell/main/audio-codec/include/MP3Decoder.h
Normal file
26
lib/spotify/cspot/bell/main/audio-codec/include/MP3Decoder.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h> // for uint8_t, uint32_t, int16_t
|
||||
|
||||
#include "BaseCodec.h" // for BaseCodec
|
||||
#include "mp3dec.h" // for HMP3Decoder, MP3FrameInfo
|
||||
|
||||
namespace bell {
|
||||
class AudioContainer;
|
||||
|
||||
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
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h> // for uint8_t, uint32_t, int16_t
|
||||
|
||||
#include "BaseCodec.h" // for BaseCodec
|
||||
|
||||
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
|
||||
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h> // for uint8_t, uint32_t, int16_t
|
||||
|
||||
#include "BaseCodec.h" // for BaseCodec
|
||||
#include "ivorbiscodec.h" // for vorbis_comment, vorbis_dsp_state, vorbis_info
|
||||
#include "ogg.h" // for ogg_packet
|
||||
|
||||
namespace bell {
|
||||
class AudioContainer;
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user