mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-06 03:27:01 +03:00
Initial commit
faad does not work yet
This commit is contained in:
41
main/alac.c
41
main/alac.c
@@ -23,6 +23,18 @@
|
||||
|
||||
#include <alac_wrapper.h>
|
||||
|
||||
#if BYTES_PER_FRAME == 4
|
||||
#define ALIGN8(n) (n << 8)
|
||||
#define ALIGN16(n) (n)
|
||||
#define ALIGN24(n) (n >> 8)
|
||||
#define ALIGN32(n) (n >> 16)
|
||||
#else
|
||||
#define ALIGN8(n) (n << 24)
|
||||
#define ALIGN16(n) (n << 16)
|
||||
#define ALIGN24(n) (n << 8)
|
||||
#define ALIGN32(n) (n)
|
||||
#endif
|
||||
|
||||
#define BLOCK_SIZE (4096 * BYTES_PER_FRAME)
|
||||
#define MIN_READ BLOCK_SIZE
|
||||
#define MIN_SPACE (MIN_READ * 4)
|
||||
@@ -433,15 +445,15 @@ static decode_state alac_decode(void) {
|
||||
|
||||
while (frames > 0) {
|
||||
size_t f, count;
|
||||
s32_t *optr;
|
||||
ISAMPLE_T *optr;
|
||||
|
||||
IF_DIRECT(
|
||||
f = min(frames, _buf_cont_write(outputbuf) / BYTES_PER_FRAME);
|
||||
optr = (s32_t *)outputbuf->writep;
|
||||
optr = (ISAMPLE_T *)outputbuf->writep;
|
||||
);
|
||||
IF_PROCESS(
|
||||
f = min(frames, process.max_in_frames - process.in_frames);
|
||||
optr = (s32_t *)((u8_t *) process.inbuf + process.in_frames * BYTES_PER_FRAME);
|
||||
optr = (ISAMPLE_T *)((u8_t *) process.inbuf + process.in_frames * BYTES_PER_FRAME);
|
||||
);
|
||||
|
||||
f = min(f, frames);
|
||||
@@ -449,32 +461,31 @@ static decode_state alac_decode(void) {
|
||||
|
||||
if (l->sample_size == 8) {
|
||||
while (count--) {
|
||||
*optr++ = (*(u32_t*) iptr) << 24;
|
||||
*optr++ = (*(u32_t*) (iptr + 1)) << 24;
|
||||
iptr += 2;
|
||||
*optr++ = ALIGN8(*iptr++);
|
||||
*optr++ = ALIGN8(*iptr++);
|
||||
}
|
||||
} else if (l->sample_size == 16) {
|
||||
u16_t *_iptr = (u16_t*) iptr;
|
||||
while (count--) {
|
||||
*optr++ = (*(u32_t*) iptr) << 16;
|
||||
*optr++ = (*(u32_t*) (iptr + 2)) << 16;
|
||||
iptr += 4;
|
||||
*optr++ = ALIGN16(*_iptr++);
|
||||
*optr++ = ALIGN16(*_iptr++);
|
||||
}
|
||||
} else if (l->sample_size == 24) {
|
||||
while (count--) {
|
||||
*optr++ = (*(u32_t*) iptr) << 8;
|
||||
*optr++ = (*(u32_t*) (iptr + 3)) << 8;
|
||||
*optr++ = ALIGN24(*(u32_t*) iptr);
|
||||
*optr++ = ALIGN24(*(u32_t*) (iptr + 3));
|
||||
iptr += 6;
|
||||
}
|
||||
} else if (l->sample_size == 32) {
|
||||
u32_t *_iptr = (u32_t*) iptr;
|
||||
while (count--) {
|
||||
*optr++ = (*(u32_t*) iptr);
|
||||
*optr++ = (*(u32_t*) (iptr + 4));
|
||||
iptr += 8;
|
||||
*optr++ = ALIGN32(*_iptr++);
|
||||
*optr++ = ALIGN32(*_iptr++);
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("unsupported bits per sample: %u", l->sample_size);
|
||||
}
|
||||
|
||||
|
||||
frames -= f;
|
||||
|
||||
IF_DIRECT(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
CFLAGS += -DPOSIX -DLINKALL -DLOOPBACK -DDACAUDIO -DTREMOR_ONLY \
|
||||
CFLAGS += -DPOSIX -DLINKALL -DLOOPBACK -DDACAUDIO -DTREMOR_ONLY -DBYTES_PER_FRAME=4 \
|
||||
-I$(COMPONENT_PATH)/../components/codecs/inc \
|
||||
-I$(COMPONENT_PATH)/../components/codecs/inc/mad \
|
||||
-I$(COMPONENT_PATH)/../components/codecs/inc/faad2 \
|
||||
|
||||
29
main/faad.c
29
main/faad.c
@@ -23,6 +23,12 @@
|
||||
|
||||
#include <neaacdec.h>
|
||||
|
||||
#if BYTES_PER_FRAME == 4
|
||||
#define ALIGN(n) (n)
|
||||
#else
|
||||
#define ALIGN(n) (n << 8)
|
||||
#endif
|
||||
|
||||
#define WRAPBUF_LEN 2048
|
||||
|
||||
struct chunk_table {
|
||||
@@ -315,7 +321,7 @@ static decode_state faad_decode(void) {
|
||||
size_t bytes_total;
|
||||
size_t bytes_wrap;
|
||||
static NeAACDecFrameInfo info;
|
||||
s32_t *iptr;
|
||||
ISAMPLE_T *iptr;
|
||||
bool endstream;
|
||||
frames_t frames;
|
||||
|
||||
@@ -491,29 +497,35 @@ static decode_state faad_decode(void) {
|
||||
while (frames > 0) {
|
||||
frames_t f;
|
||||
frames_t count;
|
||||
s32_t *optr;
|
||||
ISAMPLE_T *optr;
|
||||
|
||||
IF_DIRECT(
|
||||
f = _buf_cont_write(outputbuf) / BYTES_PER_FRAME;
|
||||
optr = (s32_t *)outputbuf->writep;
|
||||
optr = (ISAMPLE_T *)outputbuf->writep;
|
||||
);
|
||||
IF_PROCESS(
|
||||
f = process.max_in_frames;
|
||||
optr = (s32_t *)process.inbuf;
|
||||
optr = (ISAMPLE_T *)process.inbuf;
|
||||
);
|
||||
|
||||
f = min(f, frames);
|
||||
count = f;
|
||||
|
||||
if (info.channels == 2) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
memcpy(optr, iptr, count * BYTES_PER_FRAME);
|
||||
iptr += count * 2;
|
||||
optr += count * 2;
|
||||
#else
|
||||
while (count--) {
|
||||
*optr++ = *iptr++ << 8;
|
||||
*optr++ = *iptr++ << 8;
|
||||
}
|
||||
#endif
|
||||
} else if (info.channels == 1) {
|
||||
while (count--) {
|
||||
*optr++ = *iptr << 8;
|
||||
*optr++ = *iptr++ << 8;
|
||||
*optr++ = ALIGN(*iptr);
|
||||
*optr++ = ALIGN(*iptr++);
|
||||
}
|
||||
} else {
|
||||
LOG_WARN("unsupported number of channels");
|
||||
@@ -563,7 +575,12 @@ static void faad_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
|
||||
|
||||
conf = NEAAC(a, GetCurrentConfiguration, a->hAac);
|
||||
|
||||
#if BYTES_PER_FRAME == 4
|
||||
conf->outputFormat = FAAD_FMT_16BIT;
|
||||
#else
|
||||
conf->outputFormat = FAAD_FMT_24BIT;
|
||||
#endif
|
||||
conf->defSampleRate = 44100;
|
||||
conf->downMatrix = 1;
|
||||
|
||||
if (!NEAAC(a, SetConfiguration, a->hAac, conf)) {
|
||||
|
||||
38
main/flac.c
38
main/flac.c
@@ -22,6 +22,18 @@
|
||||
|
||||
#include <FLAC/stream_decoder.h>
|
||||
|
||||
#if BYTES_PER_FRAME == 4
|
||||
#define ALIGN8(n) (n << 8)
|
||||
#define ALIGN16(n) (n)
|
||||
#define ALIGN24(n) (n >> 8)
|
||||
#define ALIGN32(n) (n >> 16)
|
||||
#else
|
||||
#define ALIGN8(n) (n << 24)
|
||||
#define ALIGN16(n) (n << 16)
|
||||
#define ALIGN24(n) (n << 8)
|
||||
#define ALIGN32(n) (n)
|
||||
#endif
|
||||
|
||||
struct flac {
|
||||
FLAC__StreamDecoder *decoder;
|
||||
#if !LINKALL
|
||||
@@ -149,45 +161,45 @@ static FLAC__StreamDecoderWriteStatus write_cb(const FLAC__StreamDecoder *decode
|
||||
while (frames > 0) {
|
||||
frames_t f;
|
||||
frames_t count;
|
||||
s32_t *optr;
|
||||
ISAMPLE_T *optr;
|
||||
|
||||
IF_DIRECT(
|
||||
optr = (s32_t *)outputbuf->writep;
|
||||
optr = (ISAMPLE_T *)outputbuf->writep;
|
||||
f = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
|
||||
);
|
||||
IF_PROCESS(
|
||||
optr = (s32_t *)process.inbuf;
|
||||
optr = (ISAMPLE_T *)process.inbuf;
|
||||
f = process.max_in_frames;
|
||||
);
|
||||
|
||||
f = min(f, frames);
|
||||
|
||||
count = f;
|
||||
|
||||
|
||||
if (bits_per_sample == 8) {
|
||||
while (count--) {
|
||||
*optr++ = *lptr++ << 24;
|
||||
*optr++ = *rptr++ << 24;
|
||||
*optr++ = ALIGN8(*lptr++);
|
||||
*optr++ = ALIGN8(*rptr++);
|
||||
}
|
||||
} else if (bits_per_sample == 16) {
|
||||
while (count--) {
|
||||
*optr++ = *lptr++ << 16;
|
||||
*optr++ = *rptr++ << 16;
|
||||
*optr++ = ALIGN16(*lptr++);
|
||||
*optr++ = ALIGN16(*rptr++);
|
||||
}
|
||||
} else if (bits_per_sample == 24) {
|
||||
while (count--) {
|
||||
*optr++ = *lptr++ << 8;
|
||||
*optr++ = *rptr++ << 8;
|
||||
*optr++ = ALIGN24(*lptr++);
|
||||
*optr++ = ALIGN24(*rptr++);
|
||||
}
|
||||
} else if (bits_per_sample == 32) {
|
||||
while (count--) {
|
||||
*optr++ = *lptr++;
|
||||
*optr++ = *rptr++;
|
||||
*optr++ = ALIGN32(*lptr++);
|
||||
*optr++ = ALIGN32(*rptr++);
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR("unsupported bits per sample: %u", bits_per_sample);
|
||||
}
|
||||
|
||||
|
||||
frames -= f;
|
||||
|
||||
IF_DIRECT(
|
||||
|
||||
17
main/mad.c
17
main/mad.c
@@ -88,15 +88,18 @@ extern struct processstate process;
|
||||
#endif
|
||||
|
||||
// based on libmad minimad.c scale
|
||||
static inline u32_t scale(mad_fixed_t sample) {
|
||||
static inline ISAMPLE_T scale(mad_fixed_t sample) {
|
||||
sample += (1L << (MAD_F_FRACBITS - 24));
|
||||
|
||||
if (sample >= MAD_F_ONE)
|
||||
sample = MAD_F_ONE - 1;
|
||||
else if (sample < -MAD_F_ONE)
|
||||
sample = -MAD_F_ONE;
|
||||
|
||||
return (s32_t)(sample >> (MAD_F_FRACBITS + 1 - 24)) << 8;
|
||||
#if BYTES_PER_FRAME == 4
|
||||
return (ISAMPLE_T)((sample >> (MAD_F_FRACBITS + 1 - 24)) >> 8);
|
||||
#else
|
||||
return (ISAMPLE_T)((sample >> (MAD_F_FRACBITS + 1 - 24)) << 8);
|
||||
#endif
|
||||
}
|
||||
|
||||
// check for id3.2 tag at start of file - http://id3.org/id3v2.4.0-structure, return length
|
||||
@@ -300,15 +303,15 @@ static decode_state mad_decode(void) {
|
||||
|
||||
while (frames > 0) {
|
||||
size_t f, count;
|
||||
s32_t *optr;
|
||||
ISAMPLE_T *optr;
|
||||
|
||||
IF_DIRECT(
|
||||
f = min(frames, _buf_cont_write(outputbuf) / BYTES_PER_FRAME);
|
||||
optr = (s32_t *)outputbuf->writep;
|
||||
optr = (ISAMPLE_T *)outputbuf->writep;
|
||||
);
|
||||
IF_PROCESS(
|
||||
f = min(frames, process.max_in_frames - process.in_frames);
|
||||
optr = (s32_t *)((u8_t *)process.inbuf + process.in_frames * BYTES_PER_FRAME);
|
||||
optr = (ISAMPLE_T *)((u8_t *)process.inbuf + process.in_frames * BYTES_PER_FRAME);
|
||||
);
|
||||
|
||||
count = f;
|
||||
@@ -317,7 +320,7 @@ static decode_state mad_decode(void) {
|
||||
*optr++ = scale(*iptrl++);
|
||||
*optr++ = scale(*iptrr++);
|
||||
}
|
||||
|
||||
|
||||
frames -= f;
|
||||
|
||||
IF_DIRECT(
|
||||
|
||||
@@ -59,7 +59,7 @@ frames_t _output_frames(frames_t avail) {
|
||||
silence = false;
|
||||
|
||||
// start when threshold met
|
||||
if (output.state == OUTPUT_BUFFER && frames > output.threshold * output.next_sample_rate / 100 && frames > output.start_frames) {
|
||||
if (output.state == OUTPUT_BUFFER && frames > output.threshold * output.next_sample_rate / 10 && frames > output.start_frames) {
|
||||
output.state = OUTPUT_RUNNING;
|
||||
LOG_INFO("start buffer frames: %u", frames);
|
||||
wake_controller();
|
||||
|
||||
74
main/pcm.c
74
main/pcm.c
@@ -21,6 +21,14 @@
|
||||
|
||||
#include "squeezelite.h"
|
||||
|
||||
#if BYTES_PER_FRAME == 4
|
||||
#define SHIFT 16
|
||||
#define OPTR_T u16_t
|
||||
#else
|
||||
#define OPTR_T u32_t
|
||||
#define SHIFT 0
|
||||
#endif
|
||||
|
||||
extern log_level loglevel;
|
||||
|
||||
extern struct buffer *streambuf;
|
||||
@@ -175,9 +183,9 @@ static void _check_header(void) {
|
||||
static decode_state pcm_decode(void) {
|
||||
unsigned bytes, in, out;
|
||||
frames_t frames, count;
|
||||
u32_t *optr;
|
||||
OPTR_T *optr;
|
||||
u8_t *iptr;
|
||||
u8_t tmp[16];
|
||||
u8_t tmp[3*8];
|
||||
|
||||
LOCK_S;
|
||||
|
||||
@@ -236,10 +244,10 @@ static decode_state pcm_decode(void) {
|
||||
}
|
||||
|
||||
IF_DIRECT(
|
||||
optr = (u32_t *)outputbuf->writep;
|
||||
optr = (OPTR_T *)outputbuf->writep;
|
||||
);
|
||||
IF_PROCESS(
|
||||
optr = (u32_t *)process.inbuf;
|
||||
optr = (OPTR_T *)process.inbuf;
|
||||
);
|
||||
iptr = (u8_t *)streambuf->readp;
|
||||
|
||||
@@ -261,47 +269,73 @@ static decode_state pcm_decode(void) {
|
||||
LOG_INFO("reached end of audio");
|
||||
frames = audio_left / bytes_per_frame;
|
||||
}
|
||||
|
||||
|
||||
count = frames * channels;
|
||||
|
||||
if (channels == 2) {
|
||||
if (sample_size == 1) {
|
||||
while (count--) {
|
||||
*optr++ = *iptr++ << 24;
|
||||
*optr++ = *iptr++ << (24-SHIFT);
|
||||
}
|
||||
} else if (sample_size == 2) {
|
||||
if (bigendian) {
|
||||
#if BYTES_PER_FRAME == 4 && !SL_LITTLE_ENDIAN
|
||||
// while loop below works as is, but memcpy is a win for that 16/16 typical case
|
||||
memcpy(optr, iptr, count * BYTES_PER_FRAME / 2);
|
||||
#else
|
||||
while (count--) {
|
||||
*optr++ = *(iptr) << 24 | *(iptr+1) << 16;
|
||||
*optr++ = *(iptr) << (24-SHIFT) | *(iptr+1) << (16-SHIFT);
|
||||
iptr += 2;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if BYTES_PER_FRAME == 4 && SL_LITTLE_ENDIAN
|
||||
// while loop below works as is, but memcpy is a win for that 16/16 typical case
|
||||
memcpy(optr, iptr, count * BYTES_PER_FRAME / 2);
|
||||
#else
|
||||
while (count--) {
|
||||
*optr++ = *(iptr) << 16 | *(iptr+1) << 24;
|
||||
*optr++ = *(iptr) << (16-SHIFT) | *(iptr+1) << (24-SHIFT);
|
||||
iptr += 2;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else if (sample_size == 3) {
|
||||
if (bigendian) {
|
||||
while (count--) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
*optr++ = *(iptr) << 8 | *(iptr+1);
|
||||
#else
|
||||
*optr++ = *(iptr) << 24 | *(iptr+1) << 16 | *(iptr+2) << 8;
|
||||
#endif
|
||||
iptr += 3;
|
||||
}
|
||||
} else {
|
||||
while (count--) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
*optr++ = *(iptr+1) | *(iptr+2) << 8;
|
||||
#else
|
||||
*optr++ = *(iptr) << 8 | *(iptr+1) << 16 | *(iptr+2) << 24;
|
||||
#endif
|
||||
iptr += 3;
|
||||
}
|
||||
}
|
||||
} else if (sample_size == 4) {
|
||||
if (bigendian) {
|
||||
while (count--) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
*optr++ = *(iptr) << 8 | *(iptr+1);
|
||||
#else
|
||||
*optr++ = *(iptr) << 24 | *(iptr+1) << 16 | *(iptr+2) << 8 | *(iptr+3);
|
||||
#endif
|
||||
iptr += 4;
|
||||
}
|
||||
} else {
|
||||
while (count--) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
*optr++ = *(iptr+2) | *(iptr+3) << 8;
|
||||
#else
|
||||
*optr++ = *(iptr) | *(iptr+1) << 8 | *(iptr+2) << 16 | *(iptr+3) << 24;
|
||||
#endif
|
||||
iptr += 4;
|
||||
}
|
||||
}
|
||||
@@ -309,21 +343,21 @@ static decode_state pcm_decode(void) {
|
||||
} else if (channels == 1) {
|
||||
if (sample_size == 1) {
|
||||
while (count--) {
|
||||
*optr = *iptr++ << 24;
|
||||
*optr = *iptr++ << (24-SHIFT);
|
||||
*(optr+1) = *optr;
|
||||
optr += 2;
|
||||
}
|
||||
} else if (sample_size == 2) {
|
||||
if (bigendian) {
|
||||
while (count--) {
|
||||
*optr = *(iptr) << 24 | *(iptr+1) << 16;
|
||||
*optr = *(iptr) << (24-SHIFT) | *(iptr+1) << (16-SHIFT);
|
||||
*(optr+1) = *optr;
|
||||
iptr += 2;
|
||||
optr += 2;
|
||||
}
|
||||
} else {
|
||||
while (count--) {
|
||||
*optr = *(iptr) << 16 | *(iptr+1) << 24;
|
||||
*optr = *(iptr) << (16-SHIFT) | *(iptr+1) << (24-SHIFT);
|
||||
*(optr+1) = *optr;
|
||||
iptr += 2;
|
||||
optr += 2;
|
||||
@@ -332,14 +366,22 @@ static decode_state pcm_decode(void) {
|
||||
} else if (sample_size == 3) {
|
||||
if (bigendian) {
|
||||
while (count--) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
*optr++ = *(iptr) << 8 | *(iptr+1);
|
||||
#else
|
||||
*optr = *(iptr) << 24 | *(iptr+1) << 16 | *(iptr+2) << 8;
|
||||
#endif
|
||||
*(optr+1) = *optr;
|
||||
iptr += 3;
|
||||
optr += 2;
|
||||
}
|
||||
} else {
|
||||
while (count--) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
*optr++ = *(iptr+1) | *(iptr+2) << 8;
|
||||
#else
|
||||
*optr = *(iptr) << 8 | *(iptr+1) << 16 | *(iptr+2) << 24;
|
||||
#endif
|
||||
*(optr+1) = *optr;
|
||||
iptr += 3;
|
||||
optr += 2;
|
||||
@@ -348,14 +390,22 @@ static decode_state pcm_decode(void) {
|
||||
} else if (sample_size == 4) {
|
||||
if (bigendian) {
|
||||
while (count--) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
*optr++ = *(iptr) << 8 | *(iptr+1);
|
||||
#else
|
||||
*optr++ = *(iptr) << 24 | *(iptr+1) << 16 | *(iptr+2) << 8 | *(iptr+3);
|
||||
#endif
|
||||
*(optr+1) = *optr;
|
||||
iptr += 4;
|
||||
optr += 2;
|
||||
}
|
||||
} else {
|
||||
while (count--) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
*optr++ = *(iptr+2) | *(iptr+3) << 8;
|
||||
#else
|
||||
*optr++ = *(iptr) | *(iptr+1) << 8 | *(iptr+2) << 16 | *(iptr+3) << 24;
|
||||
#endif
|
||||
*(optr+1) = *optr;
|
||||
iptr += 4;
|
||||
optr += 2;
|
||||
@@ -365,7 +415,7 @@ static decode_state pcm_decode(void) {
|
||||
} else {
|
||||
LOG_ERROR("unsupported channels");
|
||||
}
|
||||
|
||||
|
||||
LOG_SDEBUG("decoded %u frames", frames);
|
||||
|
||||
_buf_inc_readp(streambuf, frames * bytes_per_frame);
|
||||
|
||||
@@ -444,7 +444,15 @@ void _wake_create(event_event*);
|
||||
|
||||
#define FIXED_ONE 0x10000
|
||||
|
||||
#ifndef BYTES_PER_FRAME
|
||||
#define BYTES_PER_FRAME 8
|
||||
#endif
|
||||
|
||||
#if BYTES_PER_FRAME == 8
|
||||
#define ISAMPLE_T s32_t
|
||||
#else
|
||||
#define ISAMPLE_T s16_t
|
||||
#endif
|
||||
|
||||
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
@@ -643,7 +651,7 @@ struct outputstate {
|
||||
unsigned latency;
|
||||
int pa_hostapi_option;
|
||||
#endif
|
||||
int (* write_cb)(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr);
|
||||
int (* write_cb)(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr);
|
||||
unsigned start_frames;
|
||||
unsigned frames_played;
|
||||
unsigned frames_played_dmp;// frames played at the point delay is measured
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
|
||||
#include "squeezelite.h"
|
||||
|
||||
#if BYTES_PER_FRAME == 4
|
||||
#define ALIGN(n) (n)
|
||||
#else
|
||||
#define ALIGN(n) (n << 16)
|
||||
#endif
|
||||
|
||||
// automatically select between floating point (preferred) and fixed point libraries:
|
||||
// NOTE: works with Tremor version here: http://svn.xiph.org/trunk/Tremor, not vorbisidec.1.0.2 currently in ubuntu
|
||||
|
||||
@@ -207,26 +213,29 @@ static decode_state vorbis_decode(void) {
|
||||
|
||||
frames_t count;
|
||||
s16_t *iptr;
|
||||
s32_t *optr;
|
||||
ISAMPLE_T *optr;
|
||||
|
||||
frames = n / 2 / channels;
|
||||
count = frames * channels;
|
||||
|
||||
// work backward to unpack samples to 4 bytes per sample
|
||||
iptr = (s16_t *)write_buf + count;
|
||||
optr = (s32_t *)write_buf + frames * 2;
|
||||
optr = (ISAMPLE_T *)write_buf + frames * 2;
|
||||
|
||||
if (channels == 2) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
memcpy(optr, iptr, count * BYTES_PER_FRAME / 2);
|
||||
#else
|
||||
while (count--) {
|
||||
*--optr = *--iptr << 16;
|
||||
}
|
||||
#endif
|
||||
} else if (channels == 1) {
|
||||
while (count--) {
|
||||
*--optr = *--iptr << 16;
|
||||
*--optr = *iptr << 16;
|
||||
*--optr = ALIGN(*--iptr);
|
||||
*--optr = ALIGN(*iptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IF_DIRECT(
|
||||
_buf_inc_writep(outputbuf, frames * BYTES_PER_FRAME);
|
||||
);
|
||||
|
||||
103
output_bt.c
103
output_bt.c
@@ -29,6 +29,7 @@ static bool running = true;
|
||||
|
||||
extern struct outputstate output;
|
||||
extern struct buffer *outputbuf;
|
||||
extern struct buffer *streambuf;
|
||||
|
||||
#define LOCK mutex_lock(outputbuf->mutex)
|
||||
#define UNLOCK mutex_unlock(outputbuf->mutex)
|
||||
@@ -36,20 +37,19 @@ extern struct buffer *outputbuf;
|
||||
#define FRAME_BLOCK MAX_SILENCE_FRAMES
|
||||
|
||||
extern u8_t *silencebuf;
|
||||
static u8_t *optr;
|
||||
|
||||
// buffer to hold output data so we can block on writing outside of output lock, allocated on init
|
||||
static u8_t *buf;
|
||||
static unsigned buffill;
|
||||
static int bytes_per_frame;
|
||||
|
||||
static int _bt_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
|
||||
s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr);
|
||||
static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
|
||||
s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr);
|
||||
|
||||
void set_volume(unsigned left, unsigned right) {
|
||||
LOG_DEBUG("setting internal gain left: %u right: %u", left, right);
|
||||
LOCK;
|
||||
output.gainL = left;
|
||||
output.gainR = right;
|
||||
// TODO
|
||||
output.gainL = FIXED_ONE;
|
||||
output.gainR = FIXED_ONE;
|
||||
UNLOCK;
|
||||
}
|
||||
|
||||
@@ -127,26 +127,12 @@ void output_init_dac(log_level level, unsigned output_buf_size, char *params, un
|
||||
|
||||
LOG_INFO("init output BT");
|
||||
|
||||
buf = malloc(FRAME_BLOCK * BYTES_PER_FRAME);
|
||||
if (!buf) {
|
||||
LOG_ERROR("unable to malloc buf");
|
||||
return;
|
||||
}
|
||||
buffill = 0;
|
||||
|
||||
memset(&output, 0, sizeof(output));
|
||||
|
||||
output.format = S32_LE;
|
||||
output.start_frames = FRAME_BLOCK * 2;
|
||||
output.write_cb = &_bt_write_frames;
|
||||
output.write_cb = &_write_frames;
|
||||
output.rate_delay = rate_delay;
|
||||
|
||||
if (params) {
|
||||
if (!strcmp(params, "32")) output.format = S32_LE;
|
||||
if (!strcmp(params, "24")) output.format = S24_3LE;
|
||||
if (!strcmp(params, "16")) output.format = S16_LE;
|
||||
}
|
||||
|
||||
// ensure output rate is specified to avoid test open
|
||||
if (!rates[0]) {
|
||||
rates[0] = 44100;
|
||||
@@ -226,32 +212,46 @@ void output_close_dac(void) {
|
||||
running = false;
|
||||
UNLOCK;
|
||||
|
||||
free(buf);
|
||||
|
||||
output_close_common();
|
||||
}
|
||||
|
||||
static int _bt_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
|
||||
s32_t cross_gain_in, s32_t cross_gain_out, s32_t **cross_ptr) {
|
||||
|
||||
u8_t *obuf;
|
||||
|
||||
static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR,
|
||||
s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr) {
|
||||
|
||||
if (!silence) {
|
||||
|
||||
|
||||
/* TODO need 16 bit fix
|
||||
if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) {
|
||||
_apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr);
|
||||
}
|
||||
|
||||
if (gainL != FIXED_ONE || gainR!= FIXED_ONE) {
|
||||
_apply_gain(outputbuf, out_frames, gainL, gainR);
|
||||
}
|
||||
*/
|
||||
|
||||
obuf = outputbuf->readp;
|
||||
#if BYTES_PER_FRAME == 4
|
||||
memcpy(optr, outputbuf->readp, out_frames * BYTES_PER_FRAME);
|
||||
#else
|
||||
{
|
||||
frames_t count = out_frames;
|
||||
s32_t *_iptr = (s32_t*) outputbuf->readp;
|
||||
s16_t *_optr = (s32_t*) optr;
|
||||
while (count--) {
|
||||
*_optr++ = *_iptr++ >> 16;
|
||||
*_optr++ = *_iptr++ >> 16;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
|
||||
obuf = silencebuf;
|
||||
u8_t *buf = silencebuf;
|
||||
|
||||
memcpy(optr, buf, out_frames * 4);
|
||||
}
|
||||
|
||||
_scale_and_pack_frames(buf + buffill * bytes_per_frame, (s32_t *)(void *)obuf, out_frames, gainL, gainR, output.format);
|
||||
|
||||
buffill += out_frames;
|
||||
|
||||
optr += out_frames * 4;
|
||||
|
||||
return (int)out_frames;
|
||||
}
|
||||
@@ -495,18 +495,16 @@ static void bt_app_a2d_cb(esp_a2d_cb_event_t event, esp_a2d_cb_param_t *param)
|
||||
static int32_t bt_app_a2d_data_cb(uint8_t *data, int32_t len)
|
||||
{
|
||||
frames_t frames;
|
||||
int i;
|
||||
s16_t *optr = (s16_t*) data;
|
||||
s32_t *iptr = (s32_t*) buf;
|
||||
static int count = 0;
|
||||
|
||||
if (len < 0 || data == NULL) {
|
||||
if (len < 0 || data == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOCK;
|
||||
|
||||
/* TODO
|
||||
Normally, we would want BT to not call us back unless we have not in BUFFERING state.
|
||||
Normally, we would want BT to not call us back unless we are not in BUFFERING state.
|
||||
That requires BT to not start until we are > OUTPUT_BUFFER
|
||||
// come back later, we are buffering (or stopped, need to handle that case ...) but we don't want silence
|
||||
if (output.state <= OUTPUT_BUFFER) {
|
||||
@@ -515,34 +513,21 @@ static int32_t bt_app_a2d_data_cb(uint8_t *data, int32_t len)
|
||||
}
|
||||
*/
|
||||
|
||||
switch (output.format) {
|
||||
case S32_LE:
|
||||
bytes_per_frame = 4 * 2; break;
|
||||
case S24_3LE:
|
||||
bytes_per_frame = 3 * 2; break;
|
||||
case S16_LE:
|
||||
bytes_per_frame = 2 * 2; break;
|
||||
default:
|
||||
bytes_per_frame = 4 * 2; break;
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO update with proper bytes_per_frame handling
|
||||
frames = len / 4;
|
||||
output.device_frames = 0;
|
||||
output.updated = gettime_ms();
|
||||
output.frames_played_dmp = output.frames_played;
|
||||
if (!output.threshold) output.threshold = 20;
|
||||
|
||||
optr = data;
|
||||
frames = _output_frames(frames);
|
||||
|
||||
UNLOCK;
|
||||
|
||||
for (i = 0; i < frames*2; i++) {
|
||||
*optr++ = *iptr++ >> 16;
|
||||
*optr++ = *iptr++ >> 16;
|
||||
if (!(count++ & 0x1ff)) {
|
||||
LOG_INFO("frames %d (count:%d) (out:%d, stream:%d)", frames, count, _buf_used(outputbuf), _buf_used(streambuf));
|
||||
}
|
||||
|
||||
buffill = 0;
|
||||
|
||||
return frames * 4;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ CONFIG_BT_SPP_ENABLED=n
|
||||
CONFIG_GATTS_ENABLE=n
|
||||
CONFIG_GATTC_ENABLE=n
|
||||
CONFIG_BLE_SMP_ENABLE=n
|
||||
SW_COEXIST_PREFERENCE_BALANCE=y
|
||||
#enable SPIRAM
|
||||
CONFIG_SPIRAM_SUPPORT=y
|
||||
CONFIG_SPIRAM_BOOT_INIT=y
|
||||
@@ -31,3 +32,9 @@ CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
|
||||
CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
||||
CONFIG_PARTITION_TABLE_MD5=y
|
||||
# CPU & threads options
|
||||
ESP32_DEFAULT_CPU_FREQ_240=y
|
||||
CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=
|
||||
CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0=
|
||||
CONFIG_ESP32_DEFAULT_PTHREAD_CORE_1=y
|
||||
CONFIG_ESP32_PTHREAD_TASK_CORE_DEFAULT=1
|
||||
|
||||
Reference in New Issue
Block a user