mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2025-12-09 21:17:18 +03:00
add vorbis, tweak SPIRAM/ISRAM stack
This commit is contained in:
@@ -8,12 +8,15 @@ Adding squeezelite
|
|||||||
#pragma GCC optimize ("O0")
|
#pragma GCC optimize ("O0")
|
||||||
#pragma GCC pop_options
|
#pragma GCC pop_options
|
||||||
- libflac can use espressif's version
|
- libflac can use espressif's version
|
||||||
|
- vorbis
|
||||||
|
- set SPIRAM_MALLOC_ALWAYSINTERNAL to 2048 as it consumes a lot of 8K blocks and uses all internal memory - when no memoru, WiFI chip fails
|
||||||
- set IDF_PATH=/home/esp-idf
|
- set IDF_PATH=/home/esp-idf
|
||||||
- set ESPPORT=COM9
|
- set ESPPORT=COM9
|
||||||
- change <esp-idf>\components\partition_table\partitions_singleapp.csv to 2M instead of 1M (or more)
|
- change <esp-idf>\components\partition_table\partitions_singleapp.csv to 2M instead of 1M (or more)
|
||||||
- change flash's size in serial flash config to 16M
|
- change flash's size in serial flash config to 16M
|
||||||
- change main stack size to 8000 as well (for app_main which is slimproto)
|
- change main stack size to 8000 as well (for app_main which is slimproto)
|
||||||
- use old "make" environment no CMake
|
- use old "make" environment no CMake
|
||||||
|
|
||||||
|
|
||||||
# Wifi SCAN Example
|
# Wifi SCAN Example
|
||||||
|
|
||||||
|
|||||||
@@ -2,4 +2,18 @@
|
|||||||
# "main" pseudo-component makefile.
|
# "main" pseudo-component makefile.
|
||||||
#
|
#
|
||||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||||
COMPONENT_ADD_LDFLAGS=$(COMPONENT_PATH)/lib/libmad.a $(COMPONENT_PATH)/lib/libesp-flac.a $(COMPONENT_PATH)/lib/libfaad.a -l$(COMPONENT_NAME)
|
COMPONENT_ADD_LDFLAGS=-l$(COMPONENT_NAME) \
|
||||||
|
$(COMPONENT_PATH)/lib/libmad.a \
|
||||||
|
$(COMPONENT_PATH)/lib/libesp-flac.a \
|
||||||
|
$(COMPONENT_PATH)/lib/libfaad.a \
|
||||||
|
$(COMPONENT_PATH)/lib/libvorbisidec.a \
|
||||||
|
$(COMPONENT_PATH)/lib/libogg.a
|
||||||
|
|
||||||
|
#$(COMPONENT_PATH)/lib/libvorbisidec.a
|
||||||
|
#$(COMPONENT_PATH)/lib/libogg.a
|
||||||
|
#$(COMPONENT_PATH)/lib/libesp-tremor.a
|
||||||
|
#$(COMPONENT_PATH)/lib/libesp-ogg-container.a
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
25
components/codecs/inc/ogg/config_types.h
Normal file
25
components/codecs/inc/ogg/config_types.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef __CONFIG_TYPES_H__
|
||||||
|
#define __CONFIG_TYPES_H__
|
||||||
|
|
||||||
|
/* these are filled in by configure */
|
||||||
|
#define INCLUDE_INTTYPES_H 1
|
||||||
|
#define INCLUDE_STDINT_H 1
|
||||||
|
#define INCLUDE_SYS_TYPES_H 1
|
||||||
|
|
||||||
|
#if INCLUDE_INTTYPES_H
|
||||||
|
# include <inttypes.h>
|
||||||
|
#endif
|
||||||
|
#if INCLUDE_STDINT_H
|
||||||
|
# include <stdint.h>
|
||||||
|
#endif
|
||||||
|
#if INCLUDE_SYS_TYPES_H
|
||||||
|
# include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef int16_t ogg_int16_t;
|
||||||
|
typedef uint16_t ogg_uint16_t;
|
||||||
|
typedef int32_t ogg_int32_t;
|
||||||
|
typedef uint32_t ogg_uint32_t;
|
||||||
|
typedef int64_t ogg_int64_t;
|
||||||
|
|
||||||
|
#endif
|
||||||
210
components/codecs/inc/ogg/ogg.h
Normal file
210
components/codecs/inc/ogg/ogg.h
Normal file
@@ -0,0 +1,210 @@
|
|||||||
|
/********************************************************************
|
||||||
|
* *
|
||||||
|
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||||
|
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||||
|
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||||
|
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||||
|
* *
|
||||||
|
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||||
|
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||||
|
* *
|
||||||
|
********************************************************************
|
||||||
|
|
||||||
|
function: toplevel libogg include
|
||||||
|
last mod: $Id$
|
||||||
|
|
||||||
|
********************************************************************/
|
||||||
|
#ifndef _OGG_H
|
||||||
|
#define _OGG_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <ogg/os_types.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void *iov_base;
|
||||||
|
size_t iov_len;
|
||||||
|
} ogg_iovec_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
long endbyte;
|
||||||
|
int endbit;
|
||||||
|
|
||||||
|
unsigned char *buffer;
|
||||||
|
unsigned char *ptr;
|
||||||
|
long storage;
|
||||||
|
} oggpack_buffer;
|
||||||
|
|
||||||
|
/* ogg_page is used to encapsulate the data in one Ogg bitstream page *****/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char *header;
|
||||||
|
long header_len;
|
||||||
|
unsigned char *body;
|
||||||
|
long body_len;
|
||||||
|
} ogg_page;
|
||||||
|
|
||||||
|
/* ogg_stream_state contains the current encode/decode state of a logical
|
||||||
|
Ogg bitstream **********************************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char *body_data; /* bytes from packet bodies */
|
||||||
|
long body_storage; /* storage elements allocated */
|
||||||
|
long body_fill; /* elements stored; fill mark */
|
||||||
|
long body_returned; /* elements of fill returned */
|
||||||
|
|
||||||
|
|
||||||
|
int *lacing_vals; /* The values that will go to the segment table */
|
||||||
|
ogg_int64_t *granule_vals; /* granulepos values for headers. Not compact
|
||||||
|
this way, but it is simple coupled to the
|
||||||
|
lacing fifo */
|
||||||
|
long lacing_storage;
|
||||||
|
long lacing_fill;
|
||||||
|
long lacing_packet;
|
||||||
|
long lacing_returned;
|
||||||
|
|
||||||
|
unsigned char header[282]; /* working space for header encode */
|
||||||
|
int header_fill;
|
||||||
|
|
||||||
|
int e_o_s; /* set when we have buffered the last packet in the
|
||||||
|
logical bitstream */
|
||||||
|
int b_o_s; /* set after we've written the initial page
|
||||||
|
of a logical bitstream */
|
||||||
|
long serialno;
|
||||||
|
long pageno;
|
||||||
|
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||||
|
knows where there's a hole in the data,
|
||||||
|
but we need coupling so that the codec
|
||||||
|
(which is in a separate abstraction
|
||||||
|
layer) also knows about the gap */
|
||||||
|
ogg_int64_t granulepos;
|
||||||
|
|
||||||
|
} ogg_stream_state;
|
||||||
|
|
||||||
|
/* ogg_packet is used to encapsulate the data and metadata belonging
|
||||||
|
to a single raw Ogg/Vorbis packet *************************************/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char *packet;
|
||||||
|
long bytes;
|
||||||
|
long b_o_s;
|
||||||
|
long e_o_s;
|
||||||
|
|
||||||
|
ogg_int64_t granulepos;
|
||||||
|
|
||||||
|
ogg_int64_t packetno; /* sequence number for decode; the framing
|
||||||
|
knows where there's a hole in the data,
|
||||||
|
but we need coupling so that the codec
|
||||||
|
(which is in a separate abstraction
|
||||||
|
layer) also knows about the gap */
|
||||||
|
} ogg_packet;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned char *data;
|
||||||
|
int storage;
|
||||||
|
int fill;
|
||||||
|
int returned;
|
||||||
|
|
||||||
|
int unsynced;
|
||||||
|
int headerbytes;
|
||||||
|
int bodybytes;
|
||||||
|
} ogg_sync_state;
|
||||||
|
|
||||||
|
/* Ogg BITSTREAM PRIMITIVES: bitstream ************************/
|
||||||
|
|
||||||
|
extern void oggpack_writeinit(oggpack_buffer *b);
|
||||||
|
extern int oggpack_writecheck(oggpack_buffer *b);
|
||||||
|
extern void oggpack_writetrunc(oggpack_buffer *b,long bits);
|
||||||
|
extern void oggpack_writealign(oggpack_buffer *b);
|
||||||
|
extern void oggpack_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||||
|
extern void oggpack_reset(oggpack_buffer *b);
|
||||||
|
extern void oggpack_writeclear(oggpack_buffer *b);
|
||||||
|
extern void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||||
|
extern void oggpack_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||||
|
extern long oggpack_look(oggpack_buffer *b,int bits);
|
||||||
|
extern long oggpack_look1(oggpack_buffer *b);
|
||||||
|
extern void oggpack_adv(oggpack_buffer *b,int bits);
|
||||||
|
extern void oggpack_adv1(oggpack_buffer *b);
|
||||||
|
extern long oggpack_read(oggpack_buffer *b,int bits);
|
||||||
|
extern long oggpack_read1(oggpack_buffer *b);
|
||||||
|
extern long oggpack_bytes(oggpack_buffer *b);
|
||||||
|
extern long oggpack_bits(oggpack_buffer *b);
|
||||||
|
extern unsigned char *oggpack_get_buffer(oggpack_buffer *b);
|
||||||
|
|
||||||
|
extern void oggpackB_writeinit(oggpack_buffer *b);
|
||||||
|
extern int oggpackB_writecheck(oggpack_buffer *b);
|
||||||
|
extern void oggpackB_writetrunc(oggpack_buffer *b,long bits);
|
||||||
|
extern void oggpackB_writealign(oggpack_buffer *b);
|
||||||
|
extern void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits);
|
||||||
|
extern void oggpackB_reset(oggpack_buffer *b);
|
||||||
|
extern void oggpackB_writeclear(oggpack_buffer *b);
|
||||||
|
extern void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes);
|
||||||
|
extern void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits);
|
||||||
|
extern long oggpackB_look(oggpack_buffer *b,int bits);
|
||||||
|
extern long oggpackB_look1(oggpack_buffer *b);
|
||||||
|
extern void oggpackB_adv(oggpack_buffer *b,int bits);
|
||||||
|
extern void oggpackB_adv1(oggpack_buffer *b);
|
||||||
|
extern long oggpackB_read(oggpack_buffer *b,int bits);
|
||||||
|
extern long oggpackB_read1(oggpack_buffer *b);
|
||||||
|
extern long oggpackB_bytes(oggpack_buffer *b);
|
||||||
|
extern long oggpackB_bits(oggpack_buffer *b);
|
||||||
|
extern unsigned char *oggpackB_get_buffer(oggpack_buffer *b);
|
||||||
|
|
||||||
|
/* Ogg BITSTREAM PRIMITIVES: encoding **************************/
|
||||||
|
|
||||||
|
extern int ogg_stream_packetin(ogg_stream_state *os, ogg_packet *op);
|
||||||
|
extern int ogg_stream_iovecin(ogg_stream_state *os, ogg_iovec_t *iov,
|
||||||
|
int count, long e_o_s, ogg_int64_t granulepos);
|
||||||
|
extern int ogg_stream_pageout(ogg_stream_state *os, ogg_page *og);
|
||||||
|
extern int ogg_stream_pageout_fill(ogg_stream_state *os, ogg_page *og, int nfill);
|
||||||
|
extern int ogg_stream_flush(ogg_stream_state *os, ogg_page *og);
|
||||||
|
extern int ogg_stream_flush_fill(ogg_stream_state *os, ogg_page *og, int nfill);
|
||||||
|
|
||||||
|
/* Ogg BITSTREAM PRIMITIVES: decoding **************************/
|
||||||
|
|
||||||
|
extern int ogg_sync_init(ogg_sync_state *oy);
|
||||||
|
extern int ogg_sync_clear(ogg_sync_state *oy);
|
||||||
|
extern int ogg_sync_reset(ogg_sync_state *oy);
|
||||||
|
extern int ogg_sync_destroy(ogg_sync_state *oy);
|
||||||
|
extern int ogg_sync_check(ogg_sync_state *oy);
|
||||||
|
|
||||||
|
extern char *ogg_sync_buffer(ogg_sync_state *oy, long size);
|
||||||
|
extern int ogg_sync_wrote(ogg_sync_state *oy, long bytes);
|
||||||
|
extern long ogg_sync_pageseek(ogg_sync_state *oy,ogg_page *og);
|
||||||
|
extern int ogg_sync_pageout(ogg_sync_state *oy, ogg_page *og);
|
||||||
|
extern int ogg_stream_pagein(ogg_stream_state *os, ogg_page *og);
|
||||||
|
extern int ogg_stream_packetout(ogg_stream_state *os,ogg_packet *op);
|
||||||
|
extern int ogg_stream_packetpeek(ogg_stream_state *os,ogg_packet *op);
|
||||||
|
|
||||||
|
/* Ogg BITSTREAM PRIMITIVES: general ***************************/
|
||||||
|
|
||||||
|
extern int ogg_stream_init(ogg_stream_state *os,int serialno);
|
||||||
|
extern int ogg_stream_clear(ogg_stream_state *os);
|
||||||
|
extern int ogg_stream_reset(ogg_stream_state *os);
|
||||||
|
extern int ogg_stream_reset_serialno(ogg_stream_state *os,int serialno);
|
||||||
|
extern int ogg_stream_destroy(ogg_stream_state *os);
|
||||||
|
extern int ogg_stream_check(ogg_stream_state *os);
|
||||||
|
extern int ogg_stream_eos(ogg_stream_state *os);
|
||||||
|
|
||||||
|
extern void ogg_page_checksum_set(ogg_page *og);
|
||||||
|
|
||||||
|
extern int ogg_page_version(const ogg_page *og);
|
||||||
|
extern int ogg_page_continued(const ogg_page *og);
|
||||||
|
extern int ogg_page_bos(const ogg_page *og);
|
||||||
|
extern int ogg_page_eos(const ogg_page *og);
|
||||||
|
extern ogg_int64_t ogg_page_granulepos(const ogg_page *og);
|
||||||
|
extern int ogg_page_serialno(const ogg_page *og);
|
||||||
|
extern long ogg_page_pageno(const ogg_page *og);
|
||||||
|
extern int ogg_page_packets(const ogg_page *og);
|
||||||
|
|
||||||
|
extern void ogg_packet_clear(ogg_packet *op);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _OGG_H */
|
||||||
148
components/codecs/inc/ogg/os_types.h
Normal file
148
components/codecs/inc/ogg/os_types.h
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
/********************************************************************
|
||||||
|
* *
|
||||||
|
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||||
|
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||||
|
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||||
|
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||||
|
* *
|
||||||
|
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||||
|
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||||
|
* *
|
||||||
|
********************************************************************
|
||||||
|
|
||||||
|
function: #ifdef jail to whip a few platforms into the UNIX ideal.
|
||||||
|
last mod: $Id$
|
||||||
|
|
||||||
|
********************************************************************/
|
||||||
|
#ifndef _OS_TYPES_H
|
||||||
|
#define _OS_TYPES_H
|
||||||
|
|
||||||
|
/* make it easy on the folks that want to compile the libs with a
|
||||||
|
different malloc than stdlib */
|
||||||
|
#define _ogg_malloc malloc
|
||||||
|
#define _ogg_calloc calloc
|
||||||
|
#define _ogg_realloc realloc
|
||||||
|
#define _ogg_free free
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
|
||||||
|
# if defined(__CYGWIN__)
|
||||||
|
# include <stdint.h>
|
||||||
|
typedef int16_t ogg_int16_t;
|
||||||
|
typedef uint16_t ogg_uint16_t;
|
||||||
|
typedef int32_t ogg_int32_t;
|
||||||
|
typedef uint32_t ogg_uint32_t;
|
||||||
|
typedef int64_t ogg_int64_t;
|
||||||
|
typedef uint64_t ogg_uint64_t;
|
||||||
|
# elif defined(__MINGW32__)
|
||||||
|
# include <sys/types.h>
|
||||||
|
typedef short ogg_int16_t;
|
||||||
|
typedef unsigned short ogg_uint16_t;
|
||||||
|
typedef int ogg_int32_t;
|
||||||
|
typedef unsigned int ogg_uint32_t;
|
||||||
|
typedef long long ogg_int64_t;
|
||||||
|
typedef unsigned long long ogg_uint64_t;
|
||||||
|
# elif defined(__MWERKS__)
|
||||||
|
typedef long long ogg_int64_t;
|
||||||
|
typedef int ogg_int32_t;
|
||||||
|
typedef unsigned int ogg_uint32_t;
|
||||||
|
typedef short ogg_int16_t;
|
||||||
|
typedef unsigned short ogg_uint16_t;
|
||||||
|
# else
|
||||||
|
# if defined(_MSC_VER) && (_MSC_VER >= 1800) /* MSVC 2013 and newer */
|
||||||
|
# include <stdint.h>
|
||||||
|
typedef int16_t ogg_int16_t;
|
||||||
|
typedef uint16_t ogg_uint16_t;
|
||||||
|
typedef int32_t ogg_int32_t;
|
||||||
|
typedef uint32_t ogg_uint32_t;
|
||||||
|
typedef int64_t ogg_int64_t;
|
||||||
|
typedef uint64_t ogg_uint64_t;
|
||||||
|
# else
|
||||||
|
/* MSVC/Borland */
|
||||||
|
typedef __int64 ogg_int64_t;
|
||||||
|
typedef __int32 ogg_int32_t;
|
||||||
|
typedef unsigned __int32 ogg_uint32_t;
|
||||||
|
typedef __int16 ogg_int16_t;
|
||||||
|
typedef unsigned __int16 ogg_uint16_t;
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
|
||||||
|
|
||||||
|
# include <inttypes.h>
|
||||||
|
typedef int16_t ogg_int16_t;
|
||||||
|
typedef uint16_t ogg_uint16_t;
|
||||||
|
typedef int32_t ogg_int32_t;
|
||||||
|
typedef uint32_t ogg_uint32_t;
|
||||||
|
typedef int64_t ogg_int64_t;
|
||||||
|
|
||||||
|
#elif defined(__HAIKU__)
|
||||||
|
|
||||||
|
/* Haiku */
|
||||||
|
# include <sys/types.h>
|
||||||
|
typedef short ogg_int16_t;
|
||||||
|
typedef unsigned short ogg_uint16_t;
|
||||||
|
typedef int ogg_int32_t;
|
||||||
|
typedef unsigned int ogg_uint32_t;
|
||||||
|
typedef long long ogg_int64_t;
|
||||||
|
|
||||||
|
#elif defined(__BEOS__)
|
||||||
|
|
||||||
|
/* Be */
|
||||||
|
# include <inttypes.h>
|
||||||
|
typedef int16_t ogg_int16_t;
|
||||||
|
typedef uint16_t ogg_uint16_t;
|
||||||
|
typedef int32_t ogg_int32_t;
|
||||||
|
typedef uint32_t ogg_uint32_t;
|
||||||
|
typedef int64_t ogg_int64_t;
|
||||||
|
|
||||||
|
#elif defined (__EMX__)
|
||||||
|
|
||||||
|
/* OS/2 GCC */
|
||||||
|
typedef short ogg_int16_t;
|
||||||
|
typedef unsigned short ogg_uint16_t;
|
||||||
|
typedef int ogg_int32_t;
|
||||||
|
typedef unsigned int ogg_uint32_t;
|
||||||
|
typedef long long ogg_int64_t;
|
||||||
|
|
||||||
|
#elif defined (DJGPP)
|
||||||
|
|
||||||
|
/* DJGPP */
|
||||||
|
typedef short ogg_int16_t;
|
||||||
|
typedef int ogg_int32_t;
|
||||||
|
typedef unsigned int ogg_uint32_t;
|
||||||
|
typedef long long ogg_int64_t;
|
||||||
|
|
||||||
|
#elif defined(R5900)
|
||||||
|
|
||||||
|
/* PS2 EE */
|
||||||
|
typedef long ogg_int64_t;
|
||||||
|
typedef int ogg_int32_t;
|
||||||
|
typedef unsigned ogg_uint32_t;
|
||||||
|
typedef short ogg_int16_t;
|
||||||
|
|
||||||
|
#elif defined(__SYMBIAN32__)
|
||||||
|
|
||||||
|
/* Symbian GCC */
|
||||||
|
typedef signed short ogg_int16_t;
|
||||||
|
typedef unsigned short ogg_uint16_t;
|
||||||
|
typedef signed int ogg_int32_t;
|
||||||
|
typedef unsigned int ogg_uint32_t;
|
||||||
|
typedef long long int ogg_int64_t;
|
||||||
|
|
||||||
|
#elif defined(__TMS320C6X__)
|
||||||
|
|
||||||
|
/* TI C64x compiler */
|
||||||
|
typedef signed short ogg_int16_t;
|
||||||
|
typedef unsigned short ogg_uint16_t;
|
||||||
|
typedef signed int ogg_int32_t;
|
||||||
|
typedef unsigned int ogg_uint32_t;
|
||||||
|
typedef long long int ogg_int64_t;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# include <ogg/config_types.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _OS_TYPES_H */
|
||||||
203
components/codecs/inc/vorbis/ivorbiscodec.h
Normal file
203
components/codecs/inc/vorbis/ivorbiscodec.h
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/********************************************************************
|
||||||
|
* *
|
||||||
|
* THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
|
||||||
|
* *
|
||||||
|
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||||
|
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||||
|
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||||
|
* *
|
||||||
|
* THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||||
|
* BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
|
||||||
|
* *
|
||||||
|
********************************************************************
|
||||||
|
|
||||||
|
function: libvorbis codec headers
|
||||||
|
|
||||||
|
********************************************************************/
|
||||||
|
|
||||||
|
#ifndef _vorbis_codec_h_
|
||||||
|
#define _vorbis_codec_h_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#include <ogg/ogg.h>
|
||||||
|
|
||||||
|
typedef struct vorbis_info{
|
||||||
|
int version;
|
||||||
|
int channels;
|
||||||
|
long rate;
|
||||||
|
|
||||||
|
/* The below bitrate declarations are *hints*.
|
||||||
|
Combinations of the three values carry the following implications:
|
||||||
|
|
||||||
|
all three set to the same value:
|
||||||
|
implies a fixed rate bitstream
|
||||||
|
only nominal set:
|
||||||
|
implies a VBR stream that averages the nominal bitrate. No hard
|
||||||
|
upper/lower limit
|
||||||
|
upper and or lower set:
|
||||||
|
implies a VBR bitstream that obeys the bitrate limits. nominal
|
||||||
|
may also be set to give a nominal rate.
|
||||||
|
none set:
|
||||||
|
the coder does not care to speculate.
|
||||||
|
*/
|
||||||
|
|
||||||
|
long bitrate_upper;
|
||||||
|
long bitrate_nominal;
|
||||||
|
long bitrate_lower;
|
||||||
|
long bitrate_window;
|
||||||
|
|
||||||
|
void *codec_setup;
|
||||||
|
} vorbis_info;
|
||||||
|
|
||||||
|
/* vorbis_dsp_state buffers the current vorbis audio
|
||||||
|
analysis/synthesis state. The DSP state belongs to a specific
|
||||||
|
logical bitstream ****************************************************/
|
||||||
|
typedef struct vorbis_dsp_state{
|
||||||
|
int analysisp;
|
||||||
|
vorbis_info *vi;
|
||||||
|
|
||||||
|
ogg_int32_t **pcm;
|
||||||
|
ogg_int32_t **pcmret;
|
||||||
|
int pcm_storage;
|
||||||
|
int pcm_current;
|
||||||
|
int pcm_returned;
|
||||||
|
|
||||||
|
int preextrapolate;
|
||||||
|
int eofflag;
|
||||||
|
|
||||||
|
long lW;
|
||||||
|
long W;
|
||||||
|
long nW;
|
||||||
|
long centerW;
|
||||||
|
|
||||||
|
ogg_int64_t granulepos;
|
||||||
|
ogg_int64_t sequence;
|
||||||
|
|
||||||
|
void *backend_state;
|
||||||
|
} vorbis_dsp_state;
|
||||||
|
|
||||||
|
typedef struct vorbis_block{
|
||||||
|
/* necessary stream state for linking to the framing abstraction */
|
||||||
|
ogg_int32_t **pcm; /* this is a pointer into local storage */
|
||||||
|
oggpack_buffer opb;
|
||||||
|
|
||||||
|
long lW;
|
||||||
|
long W;
|
||||||
|
long nW;
|
||||||
|
int pcmend;
|
||||||
|
int mode;
|
||||||
|
|
||||||
|
int eofflag;
|
||||||
|
ogg_int64_t granulepos;
|
||||||
|
ogg_int64_t sequence;
|
||||||
|
vorbis_dsp_state *vd; /* For read-only access of configuration */
|
||||||
|
|
||||||
|
/* local storage to avoid remallocing; it's up to the mapping to
|
||||||
|
structure it */
|
||||||
|
void *localstore;
|
||||||
|
long localtop;
|
||||||
|
long localalloc;
|
||||||
|
long totaluse;
|
||||||
|
struct alloc_chain *reap;
|
||||||
|
|
||||||
|
} vorbis_block;
|
||||||
|
|
||||||
|
/* vorbis_block is a single block of data to be processed as part of
|
||||||
|
the analysis/synthesis stream; it belongs to a specific logical
|
||||||
|
bitstream, but is independant from other vorbis_blocks belonging to
|
||||||
|
that logical bitstream. *************************************************/
|
||||||
|
|
||||||
|
struct alloc_chain{
|
||||||
|
void *ptr;
|
||||||
|
struct alloc_chain *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* vorbis_info contains all the setup information specific to the
|
||||||
|
specific compression/decompression mode in progress (eg,
|
||||||
|
psychoacoustic settings, channel setup, options, codebook
|
||||||
|
etc). vorbis_info and substructures are in backends.h.
|
||||||
|
*********************************************************************/
|
||||||
|
|
||||||
|
/* the comments are not part of vorbis_info so that vorbis_info can be
|
||||||
|
static storage */
|
||||||
|
typedef struct vorbis_comment{
|
||||||
|
/* unlimited user comment fields. libvorbis writes 'libvorbis'
|
||||||
|
whatever vendor is set to in encode */
|
||||||
|
char **user_comments;
|
||||||
|
int *comment_lengths;
|
||||||
|
int comments;
|
||||||
|
char *vendor;
|
||||||
|
|
||||||
|
} vorbis_comment;
|
||||||
|
|
||||||
|
|
||||||
|
/* libvorbis encodes in two abstraction layers; first we perform DSP
|
||||||
|
and produce a packet (see docs/analysis.txt). The packet is then
|
||||||
|
coded into a framed OggSquish bitstream by the second layer (see
|
||||||
|
docs/framing.txt). Decode is the reverse process; we sync/frame
|
||||||
|
the bitstream and extract individual packets, then decode the
|
||||||
|
packet back into PCM audio.
|
||||||
|
|
||||||
|
The extra framing/packetizing is used in streaming formats, such as
|
||||||
|
files. Over the net (such as with UDP), the framing and
|
||||||
|
packetization aren't necessary as they're provided by the transport
|
||||||
|
and the streaming layer is not used */
|
||||||
|
|
||||||
|
/* Vorbis PRIMITIVES: general ***************************************/
|
||||||
|
|
||||||
|
extern void vorbis_info_init(vorbis_info *vi);
|
||||||
|
extern void vorbis_info_clear(vorbis_info *vi);
|
||||||
|
extern int vorbis_info_blocksize(vorbis_info *vi,int zo);
|
||||||
|
extern void vorbis_comment_init(vorbis_comment *vc);
|
||||||
|
extern void vorbis_comment_add(vorbis_comment *vc, char *comment);
|
||||||
|
extern void vorbis_comment_add_tag(vorbis_comment *vc,
|
||||||
|
char *tag, char *contents);
|
||||||
|
extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count);
|
||||||
|
extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag);
|
||||||
|
extern void vorbis_comment_clear(vorbis_comment *vc);
|
||||||
|
|
||||||
|
extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb);
|
||||||
|
extern int vorbis_block_clear(vorbis_block *vb);
|
||||||
|
extern void vorbis_dsp_clear(vorbis_dsp_state *v);
|
||||||
|
|
||||||
|
/* Vorbis PRIMITIVES: synthesis layer *******************************/
|
||||||
|
extern int vorbis_synthesis_idheader(ogg_packet *op);
|
||||||
|
extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,
|
||||||
|
ogg_packet *op);
|
||||||
|
|
||||||
|
extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi);
|
||||||
|
extern int vorbis_synthesis_restart(vorbis_dsp_state *v);
|
||||||
|
extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op);
|
||||||
|
extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op);
|
||||||
|
extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb);
|
||||||
|
extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,ogg_int32_t ***pcm);
|
||||||
|
extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples);
|
||||||
|
extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
|
||||||
|
|
||||||
|
/* Vorbis ERRORS and return codes ***********************************/
|
||||||
|
|
||||||
|
#define OV_FALSE -1
|
||||||
|
#define OV_EOF -2
|
||||||
|
#define OV_HOLE -3
|
||||||
|
|
||||||
|
#define OV_EREAD -128
|
||||||
|
#define OV_EFAULT -129
|
||||||
|
#define OV_EIMPL -130
|
||||||
|
#define OV_EINVAL -131
|
||||||
|
#define OV_ENOTVORBIS -132
|
||||||
|
#define OV_EBADHEADER -133
|
||||||
|
#define OV_EVERSION -134
|
||||||
|
#define OV_ENOTAUDIO -135
|
||||||
|
#define OV_EBADPACKET -136
|
||||||
|
#define OV_EBADLINK -137
|
||||||
|
#define OV_ENOSEEK -138
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif
|
||||||
130
components/codecs/inc/vorbis/vorbisfile.h
Normal file
130
components/codecs/inc/vorbis/vorbisfile.h
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/********************************************************************
|
||||||
|
* *
|
||||||
|
* THIS FILE IS PART OF THE OggVorbis 'TREMOR' CODEC SOURCE CODE. *
|
||||||
|
* *
|
||||||
|
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||||
|
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||||
|
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||||
|
* *
|
||||||
|
* THE OggVorbis 'TREMOR' SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||||
|
* BY THE Xiph.Org FOUNDATION http://www.xiph.org/ *
|
||||||
|
* *
|
||||||
|
********************************************************************
|
||||||
|
|
||||||
|
function: stdio-based convenience library for opening/seeking/decoding
|
||||||
|
|
||||||
|
********************************************************************/
|
||||||
|
|
||||||
|
#ifndef _OV_FILE_H_
|
||||||
|
#define _OV_FILE_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "ivorbiscodec.h"
|
||||||
|
|
||||||
|
#define CHUNKSIZE 65535
|
||||||
|
#define READSIZE 1024
|
||||||
|
/* The function prototypes for the callbacks are basically the same as for
|
||||||
|
* the stdio functions fread, fseek, fclose, ftell.
|
||||||
|
* The one difference is that the FILE * arguments have been replaced with
|
||||||
|
* a void * - this is to be used as a pointer to whatever internal data these
|
||||||
|
* functions might need. In the stdio case, it's just a FILE * cast to a void *
|
||||||
|
*
|
||||||
|
* If you use other functions, check the docs for these functions and return
|
||||||
|
* the right values. For seek_func(), you *MUST* return -1 if the stream is
|
||||||
|
* unseekable
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
size_t (*read_func) (void *ptr, size_t size, size_t nmemb, void *datasource);
|
||||||
|
int (*seek_func) (void *datasource, ogg_int64_t offset, int whence);
|
||||||
|
int (*close_func) (void *datasource);
|
||||||
|
long (*tell_func) (void *datasource);
|
||||||
|
} ov_callbacks;
|
||||||
|
|
||||||
|
#define NOTOPEN 0
|
||||||
|
#define PARTOPEN 1
|
||||||
|
#define OPENED 2
|
||||||
|
#define STREAMSET 3
|
||||||
|
#define INITSET 4
|
||||||
|
|
||||||
|
typedef struct OggVorbis_File {
|
||||||
|
void *datasource; /* Pointer to a FILE *, etc. */
|
||||||
|
int seekable;
|
||||||
|
ogg_int64_t offset;
|
||||||
|
ogg_int64_t end;
|
||||||
|
ogg_sync_state oy;
|
||||||
|
|
||||||
|
/* If the FILE handle isn't seekable (eg, a pipe), only the current
|
||||||
|
stream appears */
|
||||||
|
int links;
|
||||||
|
ogg_int64_t *offsets;
|
||||||
|
ogg_int64_t *dataoffsets;
|
||||||
|
ogg_uint32_t *serialnos;
|
||||||
|
ogg_int64_t *pcmlengths;
|
||||||
|
vorbis_info *vi;
|
||||||
|
vorbis_comment *vc;
|
||||||
|
|
||||||
|
/* Decoding working state local storage */
|
||||||
|
ogg_int64_t pcm_offset;
|
||||||
|
int ready_state;
|
||||||
|
ogg_uint32_t current_serialno;
|
||||||
|
int current_link;
|
||||||
|
|
||||||
|
ogg_int64_t bittrack;
|
||||||
|
ogg_int64_t samptrack;
|
||||||
|
|
||||||
|
ogg_stream_state os; /* take physical pages, weld into a logical
|
||||||
|
stream of packets */
|
||||||
|
vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
|
||||||
|
vorbis_block vb; /* local working space for packet->PCM decode */
|
||||||
|
|
||||||
|
ov_callbacks callbacks;
|
||||||
|
|
||||||
|
} OggVorbis_File;
|
||||||
|
|
||||||
|
extern int ov_clear(OggVorbis_File *vf);
|
||||||
|
extern int ov_open(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes);
|
||||||
|
extern int ov_open_callbacks(void *datasource, OggVorbis_File *vf,
|
||||||
|
const char *initial, long ibytes, ov_callbacks callbacks);
|
||||||
|
|
||||||
|
extern int ov_test(FILE *f,OggVorbis_File *vf,const char *initial,long ibytes);
|
||||||
|
extern int ov_test_callbacks(void *datasource, OggVorbis_File *vf,
|
||||||
|
const char *initial, long ibytes, ov_callbacks callbacks);
|
||||||
|
extern int ov_test_open(OggVorbis_File *vf);
|
||||||
|
|
||||||
|
extern long ov_bitrate(OggVorbis_File *vf,int i);
|
||||||
|
extern long ov_bitrate_instant(OggVorbis_File *vf);
|
||||||
|
extern long ov_streams(OggVorbis_File *vf);
|
||||||
|
extern long ov_seekable(OggVorbis_File *vf);
|
||||||
|
extern long ov_serialnumber(OggVorbis_File *vf,int i);
|
||||||
|
|
||||||
|
extern ogg_int64_t ov_raw_total(OggVorbis_File *vf,int i);
|
||||||
|
extern ogg_int64_t ov_pcm_total(OggVorbis_File *vf,int i);
|
||||||
|
extern ogg_int64_t ov_time_total(OggVorbis_File *vf,int i);
|
||||||
|
|
||||||
|
extern int ov_raw_seek(OggVorbis_File *vf,ogg_int64_t pos);
|
||||||
|
extern int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos);
|
||||||
|
extern int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos);
|
||||||
|
extern int ov_time_seek(OggVorbis_File *vf,ogg_int64_t pos);
|
||||||
|
extern int ov_time_seek_page(OggVorbis_File *vf,ogg_int64_t pos);
|
||||||
|
|
||||||
|
extern ogg_int64_t ov_raw_tell(OggVorbis_File *vf);
|
||||||
|
extern ogg_int64_t ov_pcm_tell(OggVorbis_File *vf);
|
||||||
|
extern ogg_int64_t ov_time_tell(OggVorbis_File *vf);
|
||||||
|
|
||||||
|
extern vorbis_info *ov_info(OggVorbis_File *vf,int link);
|
||||||
|
extern vorbis_comment *ov_comment(OggVorbis_File *vf,int link);
|
||||||
|
|
||||||
|
extern long ov_read(OggVorbis_File *vf,char *buffer,int length,
|
||||||
|
int *bitstream);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
BIN
components/codecs/lib/libesp-ogg-container.a
Normal file
BIN
components/codecs/lib/libesp-ogg-container.a
Normal file
Binary file not shown.
BIN
components/codecs/lib/libesp-tremor.a
Normal file
BIN
components/codecs/lib/libesp-tremor.a
Normal file
Binary file not shown.
BIN
components/codecs/lib/libesp_processing.a
Normal file
BIN
components/codecs/lib/libesp_processing.a
Normal file
Binary file not shown.
Binary file not shown.
BIN
components/codecs/lib/libogg.a
Normal file
BIN
components/codecs/lib/libogg.a
Normal file
Binary file not shown.
BIN
components/codecs/lib/libvorbisidec.a
Normal file
BIN
components/codecs/lib/libvorbisidec.a
Normal file
Binary file not shown.
@@ -54,6 +54,7 @@ static bool running = true;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void *decode_thread() {
|
static void *decode_thread() {
|
||||||
|
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
size_t bytes, space, min_space;
|
size_t bytes, space, min_space;
|
||||||
@@ -171,10 +172,8 @@ void decode_init(log_level level, const char *include_codecs, const char *exclud
|
|||||||
if (!strstr(exclude_codecs, "aac") && (!include_codecs || (order_codecs = strstr(include_codecs, "aac"))))
|
if (!strstr(exclude_codecs, "aac") && (!include_codecs || (order_codecs = strstr(include_codecs, "aac"))))
|
||||||
sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_faad());
|
sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_faad());
|
||||||
#endif
|
#endif
|
||||||
/*
|
|
||||||
if (!strstr(exclude_codecs, "ogg") && (!include_codecs || (order_codecs = strstr(include_codecs, "ogg"))))
|
if (!strstr(exclude_codecs, "ogg") && (!include_codecs || (order_codecs = strstr(include_codecs, "ogg"))))
|
||||||
sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_vorbis());
|
sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_vorbis());
|
||||||
*/
|
|
||||||
|
|
||||||
if (!strstr(exclude_codecs, "flac") && (!include_codecs || (order_codecs = strstr(include_codecs, "flac"))))
|
if (!strstr(exclude_codecs, "flac") && (!include_codecs || (order_codecs = strstr(include_codecs, "flac"))))
|
||||||
sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_flac());
|
sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_flac());
|
||||||
|
|||||||
@@ -280,8 +280,12 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif /* SUN */
|
#endif /* SUN */
|
||||||
|
|
||||||
|
#ifndef PTHREAD_STACK_MIN
|
||||||
|
#define PTHREAD_STACK_MIN 256
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STREAM_THREAD_STACK_SIZE 8 * 1024
|
#define STREAM_THREAD_STACK_SIZE 8 * 1024
|
||||||
#define DECODE_THREAD_STACK_SIZE 32 * 1024
|
#define DECODE_THREAD_STACK_SIZE 20 * 1024
|
||||||
#define OUTPUT_THREAD_STACK_SIZE 8 * 1024
|
#define OUTPUT_THREAD_STACK_SIZE 8 * 1024
|
||||||
#define IR_THREAD_STACK_SIZE 8 * 1024
|
#define IR_THREAD_STACK_SIZE 8 * 1024
|
||||||
#if !OSX
|
#if !OSX
|
||||||
|
|||||||
339
main/vorbis.c
Normal file
339
main/vorbis.c
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
/*
|
||||||
|
* Squeezelite - lightweight headless squeezebox emulator
|
||||||
|
*
|
||||||
|
* (c) Adrian Smith 2012-2015, triode1@btinternet.com
|
||||||
|
* Ralph Irving 2015-2017, ralph_irving@hotmail.com
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "squeezelite.h"
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
// we take common definations from <vorbis/vorbisfile.h> even though we can use tremor at run time
|
||||||
|
// tremor's OggVorbis_File struct is normally smaller so this is ok, but padding added to malloc in case it is bigger
|
||||||
|
#define OV_EXCLUDE_STATIC_CALLBACKS
|
||||||
|
|
||||||
|
#include <vorbis/vorbisfile.h>
|
||||||
|
|
||||||
|
struct vorbis {
|
||||||
|
OggVorbis_File *vf;
|
||||||
|
bool opened;
|
||||||
|
#if !LINKALL
|
||||||
|
// vorbis symbols to be dynamically loaded - from either vorbisfile or vorbisidec (tremor) version of library
|
||||||
|
vorbis_info *(* ov_info)(OggVorbis_File *vf, int link);
|
||||||
|
int (* ov_clear)(OggVorbis_File *vf);
|
||||||
|
long (* ov_read)(OggVorbis_File *vf, char *buffer, int length, int bigendianp, int word, int sgned, int *bitstream);
|
||||||
|
long (* ov_read_tremor)(OggVorbis_File *vf, char *buffer, int length, int *bitstream);
|
||||||
|
int (* ov_open_callbacks)(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks);
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct vorbis *v;
|
||||||
|
|
||||||
|
extern log_level loglevel;
|
||||||
|
|
||||||
|
extern struct buffer *streambuf;
|
||||||
|
extern struct buffer *outputbuf;
|
||||||
|
extern struct streamstate stream;
|
||||||
|
extern struct outputstate output;
|
||||||
|
extern struct decodestate decode;
|
||||||
|
extern struct processstate process;
|
||||||
|
|
||||||
|
#define LOCK_S mutex_lock(streambuf->mutex)
|
||||||
|
#define UNLOCK_S mutex_unlock(streambuf->mutex)
|
||||||
|
#define LOCK_O mutex_lock(outputbuf->mutex)
|
||||||
|
#define UNLOCK_O mutex_unlock(outputbuf->mutex)
|
||||||
|
#if PROCESS
|
||||||
|
#define LOCK_O_direct if (decode.direct) mutex_lock(outputbuf->mutex)
|
||||||
|
#define UNLOCK_O_direct if (decode.direct) mutex_unlock(outputbuf->mutex)
|
||||||
|
#define LOCK_O_not_direct if (!decode.direct) mutex_lock(outputbuf->mutex)
|
||||||
|
#define UNLOCK_O_not_direct if (!decode.direct) mutex_unlock(outputbuf->mutex)
|
||||||
|
#define IF_DIRECT(x) if (decode.direct) { x }
|
||||||
|
#define IF_PROCESS(x) if (!decode.direct) { x }
|
||||||
|
#else
|
||||||
|
#define LOCK_O_direct mutex_lock(outputbuf->mutex)
|
||||||
|
#define UNLOCK_O_direct mutex_unlock(outputbuf->mutex)
|
||||||
|
#define LOCK_O_not_direct
|
||||||
|
#define UNLOCK_O_not_direct
|
||||||
|
#define IF_DIRECT(x) { x }
|
||||||
|
#define IF_PROCESS(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if LINKALL
|
||||||
|
#define OV(h, fn, ...) (ov_ ## fn)(__VA_ARGS__)
|
||||||
|
#define TREMOR(h) 0
|
||||||
|
#if !WIN
|
||||||
|
extern int ov_read_tremor(); // needed to enable compilation, not linked
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define OV(h, fn, ...) (h)->ov_##fn(__VA_ARGS__)
|
||||||
|
#define TREMOR(h) (h)->ov_read_tremor
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// called with mutex locked within vorbis_decode to avoid locking O before S
|
||||||
|
static size_t _read_cb(void *ptr, size_t size, size_t nmemb, void *datasource) {
|
||||||
|
size_t bytes;
|
||||||
|
|
||||||
|
bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
|
||||||
|
bytes = min(bytes, size * nmemb);
|
||||||
|
|
||||||
|
memcpy(ptr, streambuf->readp, bytes);
|
||||||
|
_buf_inc_readp(streambuf, bytes);
|
||||||
|
|
||||||
|
return bytes / size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// these are needed for older versions of tremor, later versions and libvorbis allow NULL to be used
|
||||||
|
static int _seek_cb(void *datasource, ogg_int64_t offset, int whence) { return -1; }
|
||||||
|
static int _close_cb(void *datasource) { return 0; }
|
||||||
|
static long _tell_cb(void *datasource) { return 0; }
|
||||||
|
|
||||||
|
static decode_state vorbis_decode(void) {
|
||||||
|
static int channels;
|
||||||
|
bool end;
|
||||||
|
frames_t frames;
|
||||||
|
int bytes, s, n;
|
||||||
|
u8_t *write_buf;
|
||||||
|
|
||||||
|
LOCK_S;
|
||||||
|
LOCK_O_direct;
|
||||||
|
end = (stream.state <= DISCONNECT);
|
||||||
|
|
||||||
|
IF_DIRECT(
|
||||||
|
frames = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
|
||||||
|
);
|
||||||
|
IF_PROCESS(
|
||||||
|
frames = process.max_in_frames;
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!frames && end) {
|
||||||
|
UNLOCK_O_direct;
|
||||||
|
UNLOCK_S;
|
||||||
|
return DECODE_COMPLETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decode.new_stream) {
|
||||||
|
ov_callbacks cbs;
|
||||||
|
int err;
|
||||||
|
struct vorbis_info *info;
|
||||||
|
|
||||||
|
cbs.read_func = _read_cb;
|
||||||
|
|
||||||
|
if (TREMOR(v)) {
|
||||||
|
cbs.seek_func = _seek_cb; cbs.close_func = _close_cb; cbs.tell_func = _tell_cb;
|
||||||
|
} else {
|
||||||
|
cbs.seek_func = NULL; cbs.close_func = NULL; cbs.tell_func = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = OV(v, open_callbacks, streambuf, v->vf, NULL, 0, cbs)) < 0) {
|
||||||
|
LOG_WARN("open_callbacks error: %d", err);
|
||||||
|
UNLOCK_O_direct;
|
||||||
|
UNLOCK_S;
|
||||||
|
return DECODE_COMPLETE;
|
||||||
|
}
|
||||||
|
v->opened = true;
|
||||||
|
|
||||||
|
info = OV(v, info, v->vf, -1);
|
||||||
|
|
||||||
|
LOG_INFO("setting track_start");
|
||||||
|
LOCK_O_not_direct;
|
||||||
|
output.next_sample_rate = decode_newstream(info->rate, output.supported_rates);
|
||||||
|
IF_DSD( output.next_fmt = PCM; )
|
||||||
|
output.track_start = outputbuf->writep;
|
||||||
|
if (output.fade_mode) _checkfade(true);
|
||||||
|
decode.new_stream = false;
|
||||||
|
UNLOCK_O_not_direct;
|
||||||
|
|
||||||
|
IF_PROCESS(
|
||||||
|
frames = process.max_in_frames;
|
||||||
|
);
|
||||||
|
|
||||||
|
channels = info->channels;
|
||||||
|
|
||||||
|
if (channels > 2) {
|
||||||
|
LOG_WARN("too many channels: %d", channels);
|
||||||
|
UNLOCK_O_direct;
|
||||||
|
UNLOCK_S;
|
||||||
|
return DECODE_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bytes = frames * 2 * channels; // samples returned are 16 bits
|
||||||
|
|
||||||
|
IF_DIRECT(
|
||||||
|
write_buf = outputbuf->writep;
|
||||||
|
);
|
||||||
|
IF_PROCESS(
|
||||||
|
write_buf = process.inbuf;
|
||||||
|
);
|
||||||
|
|
||||||
|
// write the decoded frames into outputbuf even though they are 16 bits per sample, then unpack them
|
||||||
|
#if 0
|
||||||
|
if (!TREMOR(v)) {
|
||||||
|
#if SL_LITTLE_ENDIAN
|
||||||
|
n = OV(v, read, v->vf, (char *)write_buf, bytes, 0, 2, 1, &s);
|
||||||
|
#else
|
||||||
|
n = OV(v, read, v->vf, (char *)write_buf, bytes, 1, 2, 1, &s);
|
||||||
|
#endif
|
||||||
|
#if !WIN
|
||||||
|
} else {
|
||||||
|
n = OV(v, read_tremor, v->vf, (char *)write_buf, bytes, &s);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
n = OV(v, read, v->vf, (char *)write_buf, bytes, &s);
|
||||||
|
|
||||||
|
if (n > 0) {
|
||||||
|
|
||||||
|
frames_t count;
|
||||||
|
s16_t *iptr;
|
||||||
|
s32_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;
|
||||||
|
|
||||||
|
if (channels == 2) {
|
||||||
|
while (count--) {
|
||||||
|
*--optr = *--iptr << 16;
|
||||||
|
}
|
||||||
|
} else if (channels == 1) {
|
||||||
|
while (count--) {
|
||||||
|
*--optr = *--iptr << 16;
|
||||||
|
*--optr = *iptr << 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IF_DIRECT(
|
||||||
|
_buf_inc_writep(outputbuf, frames * BYTES_PER_FRAME);
|
||||||
|
);
|
||||||
|
IF_PROCESS(
|
||||||
|
process.in_frames = frames;
|
||||||
|
);
|
||||||
|
|
||||||
|
LOG_SDEBUG("wrote %u frames", frames);
|
||||||
|
|
||||||
|
} else if (n == 0) {
|
||||||
|
|
||||||
|
LOG_INFO("end of stream");
|
||||||
|
UNLOCK_O_direct;
|
||||||
|
UNLOCK_S;
|
||||||
|
return DECODE_COMPLETE;
|
||||||
|
|
||||||
|
} else if (n == OV_HOLE) {
|
||||||
|
|
||||||
|
// recoverable hole in stream, seen when skipping
|
||||||
|
LOG_DEBUG("hole in stream");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
LOG_INFO("ov_read error: %d", n);
|
||||||
|
UNLOCK_O_direct;
|
||||||
|
UNLOCK_S;
|
||||||
|
return DECODE_COMPLETE;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNLOCK_O_direct;
|
||||||
|
UNLOCK_S;
|
||||||
|
|
||||||
|
return DECODE_RUNNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vorbis_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
|
||||||
|
if (!v->vf) {
|
||||||
|
v->vf = malloc(sizeof(OggVorbis_File) + 128); // add some padding as struct size may be larger
|
||||||
|
memset(v->vf, 0, sizeof(OggVorbis_File) + 128);
|
||||||
|
} else {
|
||||||
|
if (v->opened) {
|
||||||
|
OV(v, clear, v->vf);
|
||||||
|
v->opened = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vorbis_close(void) {
|
||||||
|
if (v->opened) {
|
||||||
|
OV(v, clear, v->vf);
|
||||||
|
v->opened = false;
|
||||||
|
}
|
||||||
|
free(v->vf);
|
||||||
|
v->vf = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool load_vorbis() {
|
||||||
|
#if !LINKALL
|
||||||
|
void *handle = dlopen(LIBVORBIS, RTLD_NOW);
|
||||||
|
char *err;
|
||||||
|
bool tremor = false;
|
||||||
|
|
||||||
|
if (!handle) {
|
||||||
|
handle = dlopen(LIBTREMOR, RTLD_NOW);
|
||||||
|
if (handle) {
|
||||||
|
tremor = true;
|
||||||
|
} else {
|
||||||
|
LOG_INFO("dlerror: %s", dlerror());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
v->ov_read = tremor ? NULL : dlsym(handle, "ov_read");
|
||||||
|
v->ov_read_tremor = tremor ? dlsym(handle, "ov_read") : NULL;
|
||||||
|
v->ov_info = dlsym(handle, "ov_info");
|
||||||
|
v->ov_clear = dlsym(handle, "ov_clear");
|
||||||
|
v->ov_open_callbacks = dlsym(handle, "ov_open_callbacks");
|
||||||
|
|
||||||
|
if ((err = dlerror()) != NULL) {
|
||||||
|
LOG_INFO("dlerror: %s", err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("loaded %s", tremor ? LIBTREMOR : LIBVORBIS);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct codec *register_vorbis(void) {
|
||||||
|
static struct codec ret = {
|
||||||
|
'o', // id
|
||||||
|
"ogg", // types
|
||||||
|
4096, // min read
|
||||||
|
40960, // min space
|
||||||
|
vorbis_open, // open
|
||||||
|
vorbis_close, // close
|
||||||
|
vorbis_decode,// decode
|
||||||
|
};
|
||||||
|
|
||||||
|
v = malloc(sizeof(struct vorbis));
|
||||||
|
if (!v) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->vf = NULL;
|
||||||
|
v->opened = false;
|
||||||
|
|
||||||
|
if (!load_vorbis()) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("using vorbis to decode ogg");
|
||||||
|
return &ret;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user