Implements the OpusCustom modes (mostly) properly

This commit is contained in:
Jean-Marc Valin 2011-09-01 13:20:40 -04:00
parent f9e701ad24
commit 06237d7b8c
14 changed files with 299 additions and 325 deletions

View file

@ -36,6 +36,13 @@ test_repacketizer_SOURCES = src/test_repacketizer.c
test_repacketizer_LDADD = libopus.la -lm test_repacketizer_LDADD = libopus.la -lm
if CUSTOM_MODES
pkginclude_HEADERS += libcelt/opus_custom.h
noinst_PROGRAMS += test_opus_custom
test_opus_custom_SOURCES = libcelt/test_opus_custom.c
test_opus_custom_LDADD = libopus.la -lm
endif
EXTRA_DIST = opus.pc.in opus-uninstalled.pc.in EXTRA_DIST = opus.pc.in opus-uninstalled.pc.in
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig

View file

@ -206,6 +206,7 @@ AC_DEFINE(OPUS_BUILD, [], [We're part of Opus])
fi fi
AM_CONDITIONAL([FIXED_POINT], [test x$ac_enable_fixed = xyes]) AM_CONDITIONAL([FIXED_POINT], [test x$ac_enable_fixed = xyes])
AM_CONDITIONAL([CUSTOM_MODES], [test x$ac_enable_custom_modes = xyes])
AC_OUTPUT([Makefile libcelt/Makefile AC_OUTPUT([Makefile libcelt/Makefile
opus.pc opus-uninstalled.pc]) opus.pc opus-uninstalled.pc])

View file

@ -23,8 +23,8 @@ for f in `cat "${toplevel}"/opus_sources.mk "${toplevel}"/celt_sources.mk \
cp -a "${toplevel}/${f}" "${destdir}/${f}" cp -a "${toplevel}/${f}" "${destdir}/${f}"
done done
cp -a "${toplevel}"/src/test_opus.c "${destdir}"/src/ cp -a "${toplevel}"/src/test_opus.c "${destdir}"/src/
cp -a "${toplevel}"/src/test_opus_custom.c "${destdir}"/src/ cp -a "${toplevel}"/libcelt/test_opus_custom.c "${destdir}"/libcelt/
cp -a "${toplevel}"/src/opus_custom.h "${destdir}"/src/ cp -a "${toplevel}"/libcelt/opus_custom.h "${destdir}"/libcelt/
cp -a "${toplevel}"/Makefile.draft "${destdir}"/Makefile cp -a "${toplevel}"/Makefile.draft "${destdir}"/Makefile
cp -a "${toplevel}"/opus_sources.mk "${destdir}"/ cp -a "${toplevel}"/opus_sources.mk "${destdir}"/
cp -a "${toplevel}"/celt_sources.mk "${destdir}"/ cp -a "${toplevel}"/celt_sources.mk "${destdir}"/

View file

@ -184,11 +184,11 @@ struct CELTEncoder {
int celt_encoder_get_size(int channels) int celt_encoder_get_size(int channels)
{ {
CELTMode *mode = celt_mode_create(48000, 960, NULL); CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
return celt_encoder_get_size_custom(mode, channels); return opus_custom_encoder_get_size(mode, channels);
} }
int celt_encoder_get_size_custom(const CELTMode *mode, int channels) int opus_custom_encoder_get_size(const CELTMode *mode, int channels)
{ {
int size = sizeof(struct CELTEncoder) int size = sizeof(struct CELTEncoder)
+ (2*channels*mode->overlap-1)*sizeof(celt_sig) + (2*channels*mode->overlap-1)*sizeof(celt_sig)
@ -197,26 +197,28 @@ int celt_encoder_get_size_custom(const CELTMode *mode, int channels)
return size; return size;
} }
CELTEncoder *celt_encoder_create_custom(const CELTMode *mode, int channels, int *error) #ifdef CUSTOM_MODES
CELTEncoder *opus_custom_encoder_create(const CELTMode *mode, int channels, int *error)
{ {
int ret; int ret;
CELTEncoder *st = (CELTEncoder *)opus_alloc(celt_encoder_get_size_custom(mode, channels)); CELTEncoder *st = (CELTEncoder *)opus_alloc(opus_custom_encoder_get_size(mode, channels));
/* init will handle the NULL case */ /* init will handle the NULL case */
ret = celt_encoder_init_custom(st, mode, channels); ret = opus_custom_encoder_init(st, mode, channels);
if (ret != OPUS_OK) if (ret != OPUS_OK)
{ {
celt_encoder_destroy(st); opus_custom_encoder_destroy(st);
st = NULL; st = NULL;
if (error)
*error = ret;
} }
if (error)
*error = ret;
return st; return st;
} }
#endif /* CUSTOM_MODES */
int celt_encoder_init(CELTEncoder *st, int sampling_rate, int channels) int celt_encoder_init(CELTEncoder *st, int sampling_rate, int channels)
{ {
int ret; int ret;
ret = celt_encoder_init_custom(st, celt_mode_create(48000, 960, NULL), channels); ret = opus_custom_encoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels);
if (ret != OPUS_OK) if (ret != OPUS_OK)
return ret; return ret;
st->upsample = resampling_factor(sampling_rate); st->upsample = resampling_factor(sampling_rate);
@ -226,7 +228,7 @@ int celt_encoder_init(CELTEncoder *st, int sampling_rate, int channels)
return OPUS_OK; return OPUS_OK;
} }
int celt_encoder_init_custom(CELTEncoder *st, const CELTMode *mode, int channels) int opus_custom_encoder_init(CELTEncoder *st, const CELTMode *mode, int channels)
{ {
if (channels < 0 || channels > 2) if (channels < 0 || channels > 2)
return OPUS_BAD_ARG; return OPUS_BAD_ARG;
@ -234,7 +236,7 @@ int celt_encoder_init_custom(CELTEncoder *st, const CELTMode *mode, int channels
if (st==NULL || mode==NULL) if (st==NULL || mode==NULL)
return OPUS_ALLOC_FAIL; return OPUS_ALLOC_FAIL;
OPUS_CLEAR((char*)st, celt_encoder_get_size_custom(mode, channels)); OPUS_CLEAR((char*)st, opus_custom_encoder_get_size(mode, channels));
st->mode = mode; st->mode = mode;
st->overlap = mode->overlap; st->overlap = mode->overlap;
@ -262,10 +264,12 @@ int celt_encoder_init_custom(CELTEncoder *st, const CELTMode *mode, int channels
return OPUS_OK; return OPUS_OK;
} }
void celt_encoder_destroy(CELTEncoder *st) #ifdef CUSTOM_MODES
void opus_custom_encoder_destroy(CELTEncoder *st)
{ {
opus_free(st); opus_free(st);
} }
#endif /* CUSTOM_MODES */
static inline opus_val16 SIG2WORD16(celt_sig x) static inline opus_val16 SIG2WORD16(celt_sig x)
{ {
@ -1647,15 +1651,16 @@ int celt_encode_with_ec(CELTEncoder * restrict st, const opus_val16 * pcm, int f
} }
#ifdef CUSTOM_MODES
#ifdef FIXED_POINT #ifdef FIXED_POINT
int celt_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) int opus_custom_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{ {
return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
} }
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) int opus_custom_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{ {
int j, ret, C, N; int j, ret, C, N;
VARDECL(opus_int16, in); VARDECL(opus_int16, in);
@ -1682,7 +1687,7 @@ int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_si
#endif /* DISABLE_FLOAT_API */ #endif /* DISABLE_FLOAT_API */
#else #else
int celt_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) int opus_custom_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{ {
int j, ret, C, N; int j, ret, C, N;
VARDECL(celt_sig, in); VARDECL(celt_sig, in);
@ -1707,14 +1712,16 @@ int celt_encode(CELTEncoder * restrict st, const opus_int16 * pcm, int frame_siz
return ret; return ret;
} }
int celt_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes) int opus_custom_encode_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes)
{ {
return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL); return celt_encode_with_ec(st, pcm, frame_size, compressed, nbCompressedBytes, NULL);
} }
#endif #endif
int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
#endif /* CUSTOM_MODES */
int opus_custom_encoder_ctl(CELTEncoder * restrict st, int request, ...)
{ {
va_list ap; va_list ap;
@ -1794,7 +1801,7 @@ int celt_encoder_ctl(CELTEncoder * restrict st, int request, ...)
case OPUS_RESET_STATE: case OPUS_RESET_STATE:
{ {
OPUS_CLEAR((char*)&st->ENCODER_RESET_START, OPUS_CLEAR((char*)&st->ENCODER_RESET_START,
celt_encoder_get_size_custom(st->mode, st->channels)- opus_custom_encoder_get_size(st->mode, st->channels)-
((char*)&st->ENCODER_RESET_START - (char*)st)); ((char*)&st->ENCODER_RESET_START - (char*)st));
st->vbr_offset = 0; st->vbr_offset = 0;
st->delayedIntra = 1; st->delayedIntra = 1;
@ -1891,11 +1898,11 @@ struct CELTDecoder {
int celt_decoder_get_size(int channels) int celt_decoder_get_size(int channels)
{ {
const CELTMode *mode = celt_mode_create(48000, 960, NULL); const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
return celt_decoder_get_size_custom(mode, channels); return opus_custom_decoder_get_size(mode, channels);
} }
int celt_decoder_get_size_custom(const CELTMode *mode, int channels) int opus_custom_decoder_get_size(const CELTMode *mode, int channels)
{ {
int size = sizeof(struct CELTDecoder) int size = sizeof(struct CELTDecoder)
+ (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig) + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig)
@ -1904,25 +1911,27 @@ int celt_decoder_get_size_custom(const CELTMode *mode, int channels)
return size; return size;
} }
CELTDecoder *celt_decoder_create_custom(const CELTMode *mode, int channels, int *error) #ifdef CUSTOM_MODES
CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error)
{ {
int ret; int ret;
CELTDecoder *st = (CELTDecoder *)opus_alloc(celt_decoder_get_size_custom(mode, channels)); CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels));
ret = celt_decoder_init_custom(st, mode, channels); ret = opus_custom_decoder_init(st, mode, channels);
if (ret != OPUS_OK) if (ret != OPUS_OK)
{ {
celt_decoder_destroy(st); opus_custom_decoder_destroy(st);
st = NULL; st = NULL;
if (error)
*error = ret;
} }
if (error)
*error = ret;
return st; return st;
} }
#endif /* CUSTOM_MODES */
int celt_decoder_init(CELTDecoder *st, int sampling_rate, int channels) int celt_decoder_init(CELTDecoder *st, int sampling_rate, int channels)
{ {
int ret; int ret;
ret = celt_decoder_init_custom(st, celt_mode_create(48000, 960, NULL), channels); ret = opus_custom_decoder_init(st, opus_custom_mode_create(48000, 960, NULL), channels);
if (ret != OPUS_OK) if (ret != OPUS_OK)
return ret; return ret;
st->downsample = resampling_factor(sampling_rate); st->downsample = resampling_factor(sampling_rate);
@ -1932,7 +1941,7 @@ int celt_decoder_init(CELTDecoder *st, int sampling_rate, int channels)
return OPUS_OK; return OPUS_OK;
} }
int celt_decoder_init_custom(CELTDecoder *st, const CELTMode *mode, int channels) int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels)
{ {
if (channels < 0 || channels > 2) if (channels < 0 || channels > 2)
return OPUS_BAD_ARG; return OPUS_BAD_ARG;
@ -1940,7 +1949,7 @@ int celt_decoder_init_custom(CELTDecoder *st, const CELTMode *mode, int channels
if (st==NULL) if (st==NULL)
return OPUS_ALLOC_FAIL; return OPUS_ALLOC_FAIL;
OPUS_CLEAR((char*)st, celt_decoder_get_size_custom(mode, channels)); OPUS_CLEAR((char*)st, opus_custom_decoder_get_size(mode, channels));
st->mode = mode; st->mode = mode;
st->overlap = mode->overlap; st->overlap = mode->overlap;
@ -1956,10 +1965,12 @@ int celt_decoder_init_custom(CELTDecoder *st, const CELTMode *mode, int channels
return OPUS_OK; return OPUS_OK;
} }
void celt_decoder_destroy(CELTDecoder *st) #ifdef CUSTOM_MODES
void opus_custom_decoder_destroy(CELTDecoder *st)
{ {
opus_free(st); opus_free(st);
} }
#endif /* CUSTOM_MODES */
static void celt_decode_lost(CELTDecoder * restrict st, opus_val16 * restrict pcm, int N, int LM) static void celt_decode_lost(CELTDecoder * restrict st, opus_val16 * restrict pcm, int N, int LM)
{ {
@ -2582,15 +2593,16 @@ int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, in
} }
#ifdef CUSTOM_MODES
#ifdef FIXED_POINT #ifdef FIXED_POINT
int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size) int opus_custom_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size)
{ {
return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL); return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
} }
#ifndef DISABLE_FLOAT_API #ifndef DISABLE_FLOAT_API
int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size) int opus_custom_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
{ {
int j, ret, C, N; int j, ret, C, N;
VARDECL(opus_int16, out); VARDECL(opus_int16, out);
@ -2615,12 +2627,12 @@ int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int
#else #else
int celt_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size) int opus_custom_decode_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size)
{ {
return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL); return celt_decode_with_ec(st, data, len, pcm, frame_size, NULL);
} }
int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size) int opus_custom_decode(CELTDecoder * restrict st, const unsigned char *data, int len, opus_int16 * restrict pcm, int frame_size)
{ {
int j, ret, C, N; int j, ret, C, N;
VARDECL(celt_sig, out); VARDECL(celt_sig, out);
@ -2644,9 +2656,10 @@ int celt_decode(CELTDecoder * restrict st, const unsigned char *data, int len, o
} }
#endif #endif
#endif /* CUSTOM_MODES */
int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...) int opus_custom_decoder_ctl(CELTDecoder * restrict st, int request, ...)
{ {
va_list ap; va_list ap;
@ -2697,7 +2710,7 @@ int celt_decoder_ctl(CELTDecoder * restrict st, int request, ...)
case OPUS_RESET_STATE: case OPUS_RESET_STATE:
{ {
OPUS_CLEAR((char*)&st->DECODER_RESET_START, OPUS_CLEAR((char*)&st->DECODER_RESET_START,
celt_decoder_get_size_custom(st->mode, st->channels)- opus_custom_decoder_get_size(st->mode, st->channels)-
((char*)&st->DECODER_RESET_START - (char*)st)); ((char*)&st->DECODER_RESET_START - (char*)st));
} }
break; break;
@ -2738,20 +2751,3 @@ bad_request:
return OPUS_UNIMPLEMENTED; return OPUS_UNIMPLEMENTED;
} }
const char *celt_strerror(int error)
{
static const char *error_strings[8] = {
"success",
"invalid argument",
"buffer too small",
"internal error",
"corrupted stream",
"request not implemented",
"invalid state",
"memory allocation failed"
};
if (error > 0 || error < -7)
return "unknown error";
else
return error_strings[-error];
}

View file

@ -37,19 +37,12 @@
#include "opus_types.h" #include "opus_types.h"
#include "opus_defines.h" #include "opus_defines.h"
#include "opus_custom.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#if defined(__GNUC__) && defined(CELT_BUILD)
#define CELT_EXPORT __attribute__ ((visibility ("default")))
#elif defined(WIN32)
#define CELT_EXPORT __declspec(dllexport)
#else
#define CELT_EXPORT
#endif
#define _celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr))) #define _celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
/* Encoder/decoder Requests */ /* Encoder/decoder Requests */
@ -80,189 +73,35 @@ extern "C" {
#define CELT_SET_END_BAND(x) CELT_SET_END_BAND_REQUEST, __opus_check_int(x) #define CELT_SET_END_BAND(x) CELT_SET_END_BAND_REQUEST, __opus_check_int(x)
/** Contains the state of an encoder. One encoder state is needed
for each stream. It is initialised once at the beginning of the
stream. Do *not* re-initialise the state for every frame.
@brief Encoder state
*/
typedef struct CELTEncoder CELTEncoder;
/** State of the decoder. One decoder state is needed for each stream.
It is initialised once at the beginning of the stream. Do *not*
re-initialise the state for every frame */
typedef struct CELTDecoder CELTDecoder;
/** The mode contains all the information necessary to create an
encoder. Both the encoder and decoder need to be initialised
with exactly the same mode, otherwise the quality will be very
bad */
typedef struct CELTMode CELTMode;
/** \defgroup codec Encoding and decoding */ /** \defgroup codec Encoding and decoding */
/* @{ */ /* @{ */
/* Mode calls */ /* Mode calls */
/** Creates a new mode struct. This will be passed to an encoder or
decoder. The mode MUST NOT BE DESTROYED until the encoders and
decoders that use it are destroyed as well.
@param Fs Sampling rate (32000 to 96000 Hz)
@param frame_size Number of samples (per channel) to encode in each
packet (even values; 64 - 512)
@param error Returned error code (if NULL, no error will be returned)
@return A newly created mode
*/
CELT_EXPORT CELTMode *celt_mode_create(opus_int32 Fs, int frame_size, int *error);
/** Destroys a mode struct. Only call this after all encoders and
decoders using this mode are destroyed as well.
@param mode Mode to be destroyed
*/
CELT_EXPORT void celt_mode_destroy(CELTMode *mode);
/* Encoder stuff */ /* Encoder stuff */
CELT_EXPORT int celt_encoder_get_size(int channels); int celt_encoder_get_size(int channels);
CELT_EXPORT int celt_encoder_get_size_custom(const CELTMode *mode, int channels);
/** Creates a new encoder state. Each stream needs its own encoder int celt_encoder_init(CELTEncoder *st, int sampling_rate, int channels);
state (can't be shared across simultaneous streams).
@param mode Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* decoder)
@param channels Number of channels
@param error Returns an error code
@return Newly created encoder state.
*/
CELT_EXPORT CELTEncoder *celt_encoder_create_custom(const CELTMode *mode, int channels, int *error);
CELT_EXPORT int celt_encoder_init(CELTEncoder *st, int sampling_rate, int channels);
CELT_EXPORT int celt_encoder_init_custom(CELTEncoder *st, const CELTMode *mode, int channels);
/** Destroys a an encoder state.
@param st Encoder state to be destroyed
*/
CELT_EXPORT void celt_encoder_destroy(CELTEncoder *st);
/** Encodes a frame of audio.
@param st Encoder state
@param pcm PCM audio in float format, with a normal range of +/-1.0.
* Samples with a range beyond +/-1.0 are supported but will
* be clipped by decoders using the integer API and should
* only be used if it is known that the far end supports
* extended dynmaic range. There must be exactly
* frame_size samples per channel.
@param compressed The compressed data is written here. This may not alias pcm or
* optional_synthesis.
@param nbCompressedBytes Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
@return Number of bytes written to "compressed". Will be the same as
* "nbCompressedBytes" unless the stream is VBR and will never be larger.
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
CELT_EXPORT int celt_encode_float(CELTEncoder *st, const float *pcm, int frame_size, unsigned char *compressed, int maxCompressedBytes);
/** Encodes a frame of audio.
@param st Encoder state
@param pcm PCM audio in signed 16-bit format (native endian). There must be
* exactly frame_size samples per channel.
@param compressed The compressed data is written here. This may not alias pcm or
* optional_synthesis.
@param nbCompressedBytes Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
@return Number of bytes written to "compressed". Will be the same as
* "nbCompressedBytes" unless the stream is VBR and will never be larger.
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
CELT_EXPORT int celt_encode(CELTEncoder *st, const opus_int16 *pcm, int frame_size, unsigned char *compressed, int maxCompressedBytes);
/** Query and set encoder parameters
@param st Encoder state
@param request Parameter to change or query
@param value Pointer to a 32-bit int value
@return Error code
*/
CELT_EXPORT int celt_encoder_ctl(CELTEncoder * st, int request, ...);
/* Decoder stuff */ /* Decoder stuff */
CELT_EXPORT int celt_decoder_get_size(int channels); int celt_decoder_get_size(int channels);
CELT_EXPORT int celt_decoder_get_size_custom(const CELTMode *mode, int channels);
/** Creates a new decoder state. Each stream needs its own decoder state (can't int celt_decoder_init(CELTDecoder *st, int sampling_rate, int channels);
be shared across simultaneous streams).
@param mode Contains all the information about the characteristics of the
stream (must be the same characteristics as used for the encoder)
@param channels Number of channels
@param error Returns an error code
@return Newly created decoder state.
*/
CELT_EXPORT CELTDecoder *celt_decoder_create(int sampling_rate, int channels, int *error);
/** Creates a new decoder state. Each stream needs its own decoder state (can't
be shared across simultaneous streams).
@param mode Contains all the information about the characteristics of the
stream (must be the same characteristics as used for the encoder)
@param channels Number of channels
@param error Returns an error code
@return Newly created decoder state.
*/
CELT_EXPORT CELTDecoder *celt_decoder_create_custom(const CELTMode *mode, int channels, int *error);
CELT_EXPORT int celt_decoder_init(CELTDecoder *st, int sampling_rate, int channels);
CELT_EXPORT int celt_decoder_init_custom(CELTDecoder *st, const CELTMode *mode, int channels);
/** Destroys a a decoder state.
@param st Decoder state to be destroyed
*/
CELT_EXPORT void celt_decoder_destroy(CELTDecoder *st);
/** Decodes a frame of audio.
@param st Decoder state
@param data Compressed data produced by an encoder
@param len Number of bytes to read from "data". This MUST be exactly the number
of bytes returned by the encoder. Using a larger value WILL NOT WORK.
@param pcm One frame (frame_size samples per channel) of decoded PCM will be
returned here in float format.
@return Error code.
*/
CELT_EXPORT int celt_decode_float(CELTDecoder *st, const unsigned char *data, int len, float *pcm, int frame_size);
/** Decodes a frame of audio.
@param st Decoder state
@param data Compressed data produced by an encoder
@param len Number of bytes to read from "data". This MUST be exactly the number
of bytes returned by the encoder. Using a larger value WILL NOT WORK.
@param pcm One frame (frame_size samples per channel) of decoded PCM will be
returned here in 16-bit PCM format (native endian).
@return Error code.
*/
CELT_EXPORT int celt_decode(CELTDecoder *st, const unsigned char *data, int len, opus_int16 *pcm, int frame_size);
/** Query and set decoder parameters
@param st Decoder state
@param request Parameter to change or query
@param value Pointer to a 32-bit int value
@return Error code
*/
CELT_EXPORT int celt_decoder_ctl(CELTDecoder * st, int request, ...);
/** Returns the English string that corresponds to an error code
* @param error Error code (negative for an error, 0 for success
* @return Constant string (must NOT be freed)
*/
CELT_EXPORT const char *celt_strerror(int error);
/* @} */ /* @} */
#define celt_encoder_ctl opus_custom_encoder_ctl
#define celt_decoder_ctl opus_custom_decoder_ctl
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -220,7 +220,7 @@ static void compute_allocation_table(CELTMode *mode)
#endif /* CUSTOM_MODES */ #endif /* CUSTOM_MODES */
CELTMode *celt_mode_create(opus_int32 Fs, int frame_size, int *error) CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error)
{ {
int i; int i;
#ifdef CUSTOM_MODES #ifdef CUSTOM_MODES
@ -392,12 +392,12 @@ failure:
if (error) if (error)
*error = OPUS_ALLOC_FAIL; *error = OPUS_ALLOC_FAIL;
if (mode!=NULL) if (mode!=NULL)
celt_mode_destroy(mode); opus_custom_mode_destroy(mode);
return NULL; return NULL;
#endif /* !CUSTOM_MODES */ #endif /* !CUSTOM_MODES */
} }
void celt_mode_destroy(CELTMode *mode) void opus_custom_mode_destroy(CELTMode *mode)
{ {
#ifdef CUSTOM_MODES #ifdef CUSTOM_MODES
int i; int i;

210
libcelt/opus_custom.h Normal file
View file

@ -0,0 +1,210 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2008 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/**
@file celt.h
@brief Contains all the functions for encoding and decoding audio
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OPUS_CUSTOM_H
#define OPUS_CUSTOM_H
#include "opus_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Contains the state of an encoder. One encoder state is needed
for each stream. It is initialised once at the beginning of the
stream. Do *not* re-initialise the state for every frame.
@brief Encoder state
*/
typedef struct CELTEncoder CELTEncoder;
/** State of the decoder. One decoder state is needed for each stream.
It is initialised once at the beginning of the stream. Do *not*
re-initialise the state for every frame */
typedef struct CELTDecoder CELTDecoder;
/** The mode contains all the information necessary to create an
encoder. Both the encoder and decoder need to be initialised
with exactly the same mode, otherwise the quality will be very
bad */
typedef struct CELTMode CELTMode;
#define OpusCustomEncoder CELTEncoder
#define OpusCustomDecoder CELTDecoder
#define OpusCustomMode CELTMode
/** Creates a new mode struct. This will be passed to an encoder or
decoder. The mode MUST NOT BE DESTROYED until the encoders and
decoders that use it are destroyed as well.
@param Fs Sampling rate (32000 to 96000 Hz)
@param frame_size Number of samples (per channel) to encode in each
packet (even values; 64 - 512)
@param error Returned error code (if NULL, no error will be returned)
@return A newly created mode
*/
OPUS_EXPORT CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
/** Destroys a mode struct. Only call this after all encoders and
decoders using this mode are destroyed as well.
@param mode Mode to be destroyed
*/
OPUS_EXPORT void opus_custom_mode_destroy(CELTMode *mode);
/* Encoder */
OPUS_EXPORT int opus_custom_encoder_get_size(const CELTMode *mode, int channels);
/** Creates a new encoder state. Each stream needs its own encoder
state (can't be shared across simultaneous streams).
@param mode Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* decoder)
@param channels Number of channels
@param error Returns an error code
@return Newly created encoder state.
*/
OPUS_EXPORT CELTEncoder *opus_custom_encoder_create(const CELTMode *mode, int channels, int *error);
OPUS_EXPORT int opus_custom_encoder_init(CELTEncoder *st, const CELTMode *mode, int channels);
/** Destroys a an encoder state.
@param st Encoder state to be destroyed
*/
OPUS_EXPORT void opus_custom_encoder_destroy(CELTEncoder *st);
/** Encodes a frame of audio.
@param st Encoder state
@param pcm PCM audio in float format, with a normal range of +/-1.0.
* Samples with a range beyond +/-1.0 are supported but will
* be clipped by decoders using the integer API and should
* only be used if it is known that the far end supports
* extended dynmaic range. There must be exactly
* frame_size samples per channel.
@param compressed The compressed data is written here. This may not alias pcm or
* optional_synthesis.
@param nbCompressedBytes Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
@return Number of bytes written to "compressed". Will be the same as
* "nbCompressedBytes" unless the stream is VBR and will never be larger.
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
OPUS_EXPORT int opus_custom_encode_float(CELTEncoder *st, const float *pcm, int frame_size, unsigned char *compressed, int maxCompressedBytes);
/** Encodes a frame of audio.
@param st Encoder state
@param pcm PCM audio in signed 16-bit format (native endian). There must be
* exactly frame_size samples per channel.
@param compressed The compressed data is written here. This may not alias pcm or
* optional_synthesis.
@param nbCompressedBytes Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
@return Number of bytes written to "compressed". Will be the same as
* "nbCompressedBytes" unless the stream is VBR and will never be larger.
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
OPUS_EXPORT int opus_custom_encode(CELTEncoder *st, const opus_int16 *pcm, int frame_size, unsigned char *compressed, int maxCompressedBytes);
/** Query and set encoder parameters
@param st Encoder state
@param request Parameter to change or query
@param value Pointer to a 32-bit int value
@return Error code
*/
OPUS_EXPORT int opus_custom_encoder_ctl(CELTEncoder * restrict st, int request, ...);
/* Decoder */
OPUS_EXPORT int opus_custom_decoder_get_size(const CELTMode *mode, int channels);
/** Creates a new decoder state. Each stream needs its own decoder state (can't
be shared across simultaneous streams).
@param mode Contains all the information about the characteristics of the
stream (must be the same characteristics as used for the encoder)
@param channels Number of channels
@param error Returns an error code
@return Newly created decoder state.
*/
OPUS_EXPORT CELTDecoder *opus_custom_decoder_create(const CELTMode *mode, int channels, int *error);
OPUS_EXPORT int opus_custom_decoder_init(CELTDecoder *st, const CELTMode *mode, int channels);
/** Destroys a a decoder state.
@param st Decoder state to be destroyed
*/
OPUS_EXPORT void opus_custom_decoder_destroy(CELTDecoder *st);
/** Decodes a frame of audio.
@param st Decoder state
@param data Compressed data produced by an encoder
@param len Number of bytes to read from "data". This MUST be exactly the number
of bytes returned by the encoder. Using a larger value WILL NOT WORK.
@param pcm One frame (frame_size samples per channel) of decoded PCM will be
returned here in float format.
@return Error code.
*/
OPUS_EXPORT int opus_custom_decode_float(CELTDecoder *st, const unsigned char *data, int len, float *pcm, int frame_size);
/** Decodes a frame of audio.
@param st Decoder state
@param data Compressed data produced by an encoder
@param len Number of bytes to read from "data". This MUST be exactly the number
of bytes returned by the encoder. Using a larger value WILL NOT WORK.
@param pcm One frame (frame_size samples per channel) of decoded PCM will be
returned here in 16-bit PCM format (native endian).
@return Error code.
*/
OPUS_EXPORT int opus_custom_decode(CELTDecoder *st, const unsigned char *data, int len, opus_int16 *pcm, int frame_size);
/** Query and set decoder parameters
@param st Decoder state
@param request Parameter to change or query
@param value Pointer to a 32-bit int value
@return Error code
*/
OPUS_EXPORT int opus_custom_decoder_ctl(CELTDecoder * restrict st, int request, ...);
#ifdef __cplusplus
}
#endif
#endif /* OPUS_CUSTOM_H */

View file

@ -150,6 +150,12 @@ extern "C" {
#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x) #define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x)
OPUS_EXPORT const char *opus_strerror(int error);
OPUS_EXPORT const char *opus_get_version_string(void);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View file

@ -44,9 +44,9 @@ int main(int argc, char *argv[])
int err; int err;
char *inFile, *outFile; char *inFile, *outFile;
FILE *fin, *fout; FILE *fin, *fout;
CELTMode *mode=NULL; OpusCustomMode *mode=NULL;
CELTEncoder *enc; OpusCustomEncoder *enc;
CELTDecoder *dec; OpusCustomDecoder *dec;
int len; int len;
opus_int32 frame_size, channels; opus_int32 frame_size, channels;
int bytes_per_packet; int bytes_per_packet;
@ -62,7 +62,7 @@ int main(int argc, char *argv[])
opus_int16 *in, *out; opus_int16 *in, *out;
if (argc != 9 && argc != 8 && argc != 7) if (argc != 9 && argc != 8 && argc != 7)
{ {
fprintf (stderr, "Usage: testcelt <rate> <channels> <frame size> " fprintf (stderr, "Usage: test_opus_custom <rate> <channels> <frame size> "
" <bytes per packet> [<complexity> [packet loss rate]] " " <bytes per packet> [<complexity> [packet loss rate]] "
"<input> <output>\n"); "<input> <output>\n");
return 1; return 1;
@ -113,12 +113,12 @@ int main(int argc, char *argv[])
fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err)); fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err));
return 1; return 1;
} }
opus_custom_decoder_ctl(dec, CELT_GET_LOOKAHEAD(&skip)); opus_custom_decoder_ctl(dec, OPUS_GET_LOOKAHEAD(&skip));
if (argc>7) if (argc>7)
{ {
complexity=atoi(argv[5]); complexity=atoi(argv[5]);
opus_custom_encoder_ctl(enc,CELT_SET_COMPLEXITY(complexity)); opus_custom_encoder_ctl(enc,OPUS_SET_COMPLEXITY(complexity));
} }
in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16)); in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));

View file

@ -101,13 +101,13 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
enc = celt_encoder_create_custom(mode, channels, &err); enc = opus_custom_encoder_create(mode, channels, &err);
if (err != 0) if (err != 0)
{ {
fprintf(stderr, "Failed to create the encoder: %s\n", celt_strerror(err)); fprintf(stderr, "Failed to create the encoder: %s\n", celt_strerror(err));
return 1; return 1;
} }
dec = celt_decoder_create_custom(mode, channels, &err); dec = opus_custom_decoder_create(mode, channels, &err);
if (err != 0) if (err != 0)
{ {
fprintf(stderr, "Failed to create the decoder: %s\n", celt_strerror(err)); fprintf(stderr, "Failed to create the decoder: %s\n", celt_strerror(err));

View file

@ -161,9 +161,6 @@ OPUS_EXPORT int opus_packet_get_nb_channels(const unsigned char *data);
OPUS_EXPORT int opus_packet_get_nb_frames(const unsigned char packet[], int len); OPUS_EXPORT int opus_packet_get_nb_frames(const unsigned char packet[], int len);
OPUS_EXPORT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], int len); OPUS_EXPORT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], int len);
OPUS_EXPORT const char *opus_strerror(int error);
OPUS_EXPORT const char *opus_get_version_string(void);
/* Repacketizer */ /* Repacketizer */
typedef struct OpusRepacketizer OpusRepacketizer; typedef struct OpusRepacketizer OpusRepacketizer;

View file

@ -1,82 +0,0 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2008 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/**
@file celt.h
@brief Contains all the functions for encoding and decoding audio
*/
/*
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef OPUS_CUSTOM_H
#define OPUS_CUSTOM_H
#ifdef ENABLE_OPUS_CUSTOM
#include "celt.h"
#include "opus.h"
#ifdef __cplusplus
extern "C" {
#endif
#define OpusCustomEncoder CELTEncoder
#define OpusCustomDecoder CELTDecoder
#define OpusCustomMode CELTMode
#define opus_custom_mode_create celt_mode_create
#define opus_custom_mode_destroy celt_mode_destroy
#define opus_custom_encoder_get_size celt_encoder_get_size_custom
#define opus_custom_encoder_create celt_encoder_create_custom
#define opus_custom_encoder_init celt_encoder_init_custom
#define opus_custom_encoder_destroy celt_encoder_destroy
#define opus_custom_encode_float celt_encode_float
#define opus_custom_encode celt_encode
#define opus_custom_encoder_ctl celt_encoder_ctl
#define opus_custom_decoder_get_size celt_decoder_get_size_custom
#define opus_custom_decoder_create celt_decoder_create_custom
#define opus_custom_decoder_init celt_decoder_init_custom
#define opus_custom_decoder_destroy celt_decoder_destroy
#define opus_custom_decode_float celt_decode_float
#define opus_custom_decode celt_decode
#define opus_custom_decoder_ctl celt_decoder_ctl
#ifdef __cplusplus
}
#endif
#endif /* ENABLE_OPUS_CUSTOM */
#endif /* OPUS_CUSTOM_H */

View file

@ -774,7 +774,7 @@ int opus_decoder_ctl(OpusDecoder *st, int request, ...)
break; break;
default: default:
/*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/ /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
ret = OPUS_BAD_ARG; ret = OPUS_UNIMPLEMENTED;
break; break;
} }

View file

@ -1014,7 +1014,7 @@ int opus_encoder_ctl(OpusEncoder *st, int request, ...)
break; break;
default: default:
/* fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);*/ /* fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);*/
ret = OPUS_BAD_ARG; ret = OPUS_UNIMPLEMENTED;
break; break;
} }
va_end(ap); va_end(ap);