shithub: opus

Download patch

ref: 06237d7b8cb26ad627fc9541e01f2437ef8b19b8
parent: f9e701ad2411b44c8689171ceb4091871574376c
author: Jean-Marc Valin <[email protected]>
date: Thu Sep 1 09:20:40 EDT 2011

Implements the OpusCustom modes (mostly) properly

--- a/Makefile.am
+++ b/Makefile.am
@@ -36,6 +36,13 @@
 
 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
 
 pkgconfigdir = $(libdir)/pkgconfig
--- a/configure.ac
+++ b/configure.ac
@@ -206,6 +206,7 @@
 fi
 
 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
            opus.pc opus-uninstalled.pc])
--- a/doc/build_draft.sh
+++ b/doc/build_draft.sh
@@ -23,8 +23,8 @@
   cp -a "${toplevel}/${f}" "${destdir}/${f}"
 done
 cp -a "${toplevel}"/src/test_opus.c "${destdir}"/src/
-cp -a "${toplevel}"/src/test_opus_custom.c "${destdir}"/src/
-cp -a "${toplevel}"/src/opus_custom.h "${destdir}"/src/
+cp -a "${toplevel}"/libcelt/test_opus_custom.c "${destdir}"/libcelt/
+cp -a "${toplevel}"/libcelt/opus_custom.h "${destdir}"/libcelt/
 cp -a "${toplevel}"/Makefile.draft "${destdir}"/Makefile
 cp -a "${toplevel}"/opus_sources.mk "${destdir}"/
 cp -a "${toplevel}"/celt_sources.mk "${destdir}"/
--- a/libcelt/celt.c
+++ b/libcelt/celt.c
@@ -184,11 +184,11 @@
 
 int celt_encoder_get_size(int channels)
 {
-   CELTMode *mode = celt_mode_create(48000, 960, NULL);
-   return celt_encoder_get_size_custom(mode, channels);
+   CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
+   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)
          + (2*channels*mode->overlap-1)*sizeof(celt_sig)
@@ -197,26 +197,28 @@
    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;
-   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 */
-   ret = celt_encoder_init_custom(st, mode, channels);
+   ret = opus_custom_encoder_init(st, mode, channels);
    if (ret != OPUS_OK)
    {
-      celt_encoder_destroy(st);
+      opus_custom_encoder_destroy(st);
       st = NULL;
-      if (error)
-         *error = ret;
    }
+   if (error)
+      *error = ret;
    return st;
 }
+#endif /* CUSTOM_MODES */
 
 int celt_encoder_init(CELTEncoder *st, int sampling_rate, int channels)
 {
    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)
       return ret;
    st->upsample = resampling_factor(sampling_rate);
@@ -226,7 +228,7 @@
       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)
       return OPUS_BAD_ARG;
@@ -234,7 +236,7 @@
    if (st==NULL || mode==NULL)
       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->overlap = mode->overlap;
@@ -262,10 +264,12 @@
    return OPUS_OK;
 }
 
-void celt_encoder_destroy(CELTEncoder *st)
+#ifdef CUSTOM_MODES
+void opus_custom_encoder_destroy(CELTEncoder *st)
 {
    opus_free(st);
 }
+#endif /* CUSTOM_MODES */
 
 static inline opus_val16 SIG2WORD16(celt_sig x)
 {
@@ -1647,15 +1651,16 @@
 }
 
 
+#ifdef CUSTOM_MODES
 
 #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);
 }
 
 #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;
    VARDECL(opus_int16, in);
@@ -1682,7 +1687,7 @@
 #endif /* DISABLE_FLOAT_API */
 #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;
    VARDECL(celt_sig, in);
@@ -1707,14 +1712,16 @@
    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);
 }
 
-
 #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;
 
@@ -1794,7 +1801,7 @@
       case OPUS_RESET_STATE:
       {
          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));
          st->vbr_offset = 0;
          st->delayedIntra = 1;
@@ -1891,11 +1898,11 @@
 
 int celt_decoder_get_size(int channels)
 {
-   const CELTMode *mode = celt_mode_create(48000, 960, NULL);
-   return celt_decoder_get_size_custom(mode, channels);
+   const CELTMode *mode = opus_custom_mode_create(48000, 960, NULL);
+   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)
             + (channels*(DECODE_BUFFER_SIZE+mode->overlap)-1)*sizeof(celt_sig)
@@ -1904,25 +1911,27 @@
    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;
-   CELTDecoder *st = (CELTDecoder *)opus_alloc(celt_decoder_get_size_custom(mode, channels));
-   ret = celt_decoder_init_custom(st, mode, channels);
+   CELTDecoder *st = (CELTDecoder *)opus_alloc(opus_custom_decoder_get_size(mode, channels));
+   ret = opus_custom_decoder_init(st, mode, channels);
    if (ret != OPUS_OK)
    {
-      celt_decoder_destroy(st);
+      opus_custom_decoder_destroy(st);
       st = NULL;
-      if (error)
-         *error = ret;
    }
+   if (error)
+      *error = ret;
    return st;
 }
+#endif /* CUSTOM_MODES */
 
 int celt_decoder_init(CELTDecoder *st, int sampling_rate, int channels)
 {
    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)
       return ret;
    st->downsample = resampling_factor(sampling_rate);
@@ -1932,7 +1941,7 @@
       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)
       return OPUS_BAD_ARG;
@@ -1940,7 +1949,7 @@
    if (st==NULL)
       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->overlap = mode->overlap;
@@ -1956,10 +1965,12 @@
    return OPUS_OK;
 }
 
-void celt_decoder_destroy(CELTDecoder *st)
+#ifdef CUSTOM_MODES
+void opus_custom_decoder_destroy(CELTDecoder *st)
 {
    opus_free(st);
 }
+#endif /* CUSTOM_MODES */
 
 static void celt_decode_lost(CELTDecoder * restrict st, opus_val16 * restrict pcm, int N, int LM)
 {
@@ -2582,15 +2593,16 @@
 }
 
 
+#ifdef CUSTOM_MODES
 
 #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);
 }
 
 #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;
    VARDECL(opus_int16, out);
@@ -2615,12 +2627,12 @@
 
 #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);
 }
 
-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;
    VARDECL(celt_sig, out);
@@ -2644,9 +2656,10 @@
 }
 
 #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;
 
@@ -2697,7 +2710,7 @@
       case OPUS_RESET_STATE:
       {
          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));
       }
       break;
@@ -2738,20 +2751,3 @@
   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];
-}
--- a/libcelt/celt.h
+++ b/libcelt/celt.h
@@ -37,19 +37,12 @@
 
 #include "opus_types.h"
 #include "opus_defines.h"
+#include "opus_custom.h"
 
 #ifdef __cplusplus
 extern "C" {
 #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)))
 
 /* Encoder/decoder Requests */
@@ -80,188 +73,34 @@
 #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 */
 /*  @{ */
 
 /* 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 */
 
-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
-    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);
+int celt_encoder_init(CELTEncoder *st, int sampling_rate, int channels);
 
-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 */
 
-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
-    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);
+int celt_decoder_init(CELTDecoder *st, int sampling_rate, 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.
- */
-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
 }
--- a/libcelt/modes.c
+++ b/libcelt/modes.c
@@ -220,7 +220,7 @@
 
 #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;
 #ifdef CUSTOM_MODES
@@ -392,12 +392,12 @@
    if (error)
       *error = OPUS_ALLOC_FAIL;
    if (mode!=NULL)
-      celt_mode_destroy(mode);
+      opus_custom_mode_destroy(mode);
    return NULL;
 #endif /* !CUSTOM_MODES */
 }
 
-void celt_mode_destroy(CELTMode *mode)
+void opus_custom_mode_destroy(CELTMode *mode)
 {
 #ifdef CUSTOM_MODES
    int i;
--- /dev/null
+++ b/libcelt/opus_custom.h
@@ -1,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 */
--- a/libcelt/opus_defines.h
+++ b/libcelt/opus_defines.h
@@ -150,6 +150,12 @@
 #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
 }
 #endif
--- /dev/null
+++ b/libcelt/test_opus_custom.c
@@ -1,0 +1,206 @@
+/* Copyright (c) 2007-2008 CSIRO
+   Copyright (c) 2007-2009 Xiph.Org Foundation
+   Written by Jean-Marc Valin */
+/*
+   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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "opus_custom.h"
+#include "arch.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+
+#define MAX_PACKET 1275
+
+int main(int argc, char *argv[])
+{
+   int err;
+   char *inFile, *outFile;
+   FILE *fin, *fout;
+   OpusCustomMode *mode=NULL;
+   OpusCustomEncoder *enc;
+   OpusCustomDecoder *dec;
+   int len;
+   opus_int32 frame_size, channels;
+   int bytes_per_packet;
+   unsigned char data[MAX_PACKET];
+   int rate;
+   int complexity;
+#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
+   int i;
+   double rmsd = 0;
+#endif
+   int count = 0;
+   opus_int32 skip;
+   opus_int16 *in, *out;
+   if (argc != 9 && argc != 8 && argc != 7)
+   {
+      fprintf (stderr, "Usage: test_opus_custom <rate> <channels> <frame size> "
+               " <bytes per packet> [<complexity> [packet loss rate]] "
+               "<input> <output>\n");
+      return 1;
+   }
+   
+   rate = atoi(argv[1]);
+   channels = atoi(argv[2]);
+   frame_size = atoi(argv[3]);
+   mode = opus_custom_mode_create(rate, frame_size, NULL);
+   if (mode == NULL)
+   {
+      fprintf(stderr, "failed to create a mode\n");
+      return 1;
+   }
+
+   bytes_per_packet = atoi(argv[4]);
+   if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET)
+   {
+      fprintf (stderr, "bytes per packet must be between 0 and %d\n",
+                        MAX_PACKET);
+      return 1;
+   }
+
+   inFile = argv[argc-2];
+   fin = fopen(inFile, "rb");
+   if (!fin)
+   {
+      fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
+      return 1;
+   }
+   outFile = argv[argc-1];
+   fout = fopen(outFile, "wb+");
+   if (!fout)
+   {
+      fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
+      return 1;
+   }
+   
+   enc = opus_custom_encoder_create(mode, channels, &err);
+   if (err != 0)
+   {
+      fprintf(stderr, "Failed to create the encoder: %s\n", opus_strerror(err));
+      return 1;
+   }
+   dec = opus_custom_decoder_create(mode, channels, &err);
+   if (err != 0)
+   {
+      fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err));
+      return 1;
+   }
+   opus_custom_decoder_ctl(dec, OPUS_GET_LOOKAHEAD(&skip));
+
+   if (argc>7)
+   {
+      complexity=atoi(argv[5]);
+      opus_custom_encoder_ctl(enc,OPUS_SET_COMPLEXITY(complexity));
+   }
+   
+   in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
+   out = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
+
+   while (!feof(fin))
+   {
+      int ret;
+      err = fread(in, sizeof(short), frame_size*channels, fin);
+      if (feof(fin))
+         break;
+      len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
+      if (len <= 0)
+         fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len));
+
+      /* This is for simulating bit errors */
+#if 0
+      int errors = 0;
+      int eid = 0;
+      /* This simulates random bit error */
+      for (i=0;i<len*8;i++)
+      {
+         if (rand()%atoi(argv[8])==0)
+         {
+            if (i<64)
+            {
+               errors++;
+               eid = i;
+            }
+            data[i/8] ^= 1<<(7-(i%8));
+         }
+      }
+      if (errors == 1)
+         data[eid/8] ^= 1<<(7-(eid%8));
+      else if (errors%2 == 1)
+         data[rand()%8] ^= 1<<rand()%8;
+#endif
+
+#if 1 /* Set to zero to use the encoder's output instead */
+      /* This is to simulate packet loss */
+      if (argc==9 && rand()%1000<atoi(argv[argc-3]))
+      /*if (errors && (errors%2==0))*/
+         ret = opus_custom_decode(dec, NULL, len, out, frame_size);
+      else
+         ret = opus_custom_decode(dec, data, len, out, frame_size);
+      if (ret < 0)
+         fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret));
+#else
+      for (i=0;i<ret*channels;i++)
+         out[i] = in[i];
+#endif
+#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
+      for (i=0;i<ret*channels;i++)
+      {
+         rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
+         /*out[i] -= in[i];*/
+      }
+#endif
+      count++;
+      fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout);
+      skip = 0;
+   }
+   PRINT_MIPS(stderr);
+   
+   opus_custom_encoder_destroy(enc);
+   opus_custom_decoder_destroy(dec);
+   fclose(fin);
+   fclose(fout);
+   opus_custom_mode_destroy(mode);
+   free(in);
+   free(out);
+#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
+   if (rmsd > 0)
+   {
+      rmsd = sqrt(rmsd/(1.0*frame_size*channels*count));
+      fprintf (stderr, "Error: encoder doesn't match decoder\n");
+      fprintf (stderr, "RMS mismatch is %f\n", rmsd);
+      return 1;
+   } else {
+      fprintf (stderr, "Encoder matches decoder!!\n");
+   }
+#endif
+   return 0;
+}
+
--- a/libcelt/testcelt.c
+++ b/libcelt/testcelt.c
@@ -101,13 +101,13 @@
       return 1;
    }
 
-   enc = celt_encoder_create_custom(mode, channels, &err);
+   enc = opus_custom_encoder_create(mode, channels, &err);
    if (err != 0)
    {
       fprintf(stderr, "Failed to create the encoder: %s\n", celt_strerror(err));
       return 1;
    }
-   dec = celt_decoder_create_custom(mode, channels, &err);
+   dec = opus_custom_decoder_create(mode, channels, &err);
    if (err != 0)
    {
       fprintf(stderr, "Failed to create the decoder: %s\n", celt_strerror(err));
--- a/src/opus.h
+++ b/src/opus.h
@@ -161,9 +161,6 @@
 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 const char *opus_strerror(int error);
-
-OPUS_EXPORT const char *opus_get_version_string(void);
 
 /* Repacketizer */
 typedef struct OpusRepacketizer OpusRepacketizer;
--- a/src/opus_custom.h
+++ /dev/null
@@ -1,82 +1,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 */
--- a/src/opus_decoder.c
+++ b/src/opus_decoder.c
@@ -774,7 +774,7 @@
    break;
    default:
       /*fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);*/
-      ret = OPUS_BAD_ARG;
+      ret = OPUS_UNIMPLEMENTED;
       break;
    }
 
--- a/src/opus_encoder.c
+++ b/src/opus_encoder.c
@@ -1014,7 +1014,7 @@
         break;
         default:
             /* fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);*/
-            ret = OPUS_BAD_ARG;
+            ret = OPUS_UNIMPLEMENTED;
             break;
     }
     va_end(ap);
--- a/src/test_opus_custom.c
+++ /dev/null
@@ -1,206 +1,0 @@
-/* Copyright (c) 2007-2008 CSIRO
-   Copyright (c) 2007-2009 Xiph.Org Foundation
-   Written by Jean-Marc Valin */
-/*
-   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.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "opus_custom.h"
-#include "arch.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-
-#define MAX_PACKET 1275
-
-int main(int argc, char *argv[])
-{
-   int err;
-   char *inFile, *outFile;
-   FILE *fin, *fout;
-   CELTMode *mode=NULL;
-   CELTEncoder *enc;
-   CELTDecoder *dec;
-   int len;
-   opus_int32 frame_size, channels;
-   int bytes_per_packet;
-   unsigned char data[MAX_PACKET];
-   int rate;
-   int complexity;
-#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
-   int i;
-   double rmsd = 0;
-#endif
-   int count = 0;
-   opus_int32 skip;
-   opus_int16 *in, *out;
-   if (argc != 9 && argc != 8 && argc != 7)
-   {
-      fprintf (stderr, "Usage: testcelt <rate> <channels> <frame size> "
-               " <bytes per packet> [<complexity> [packet loss rate]] "
-               "<input> <output>\n");
-      return 1;
-   }
-   
-   rate = atoi(argv[1]);
-   channels = atoi(argv[2]);
-   frame_size = atoi(argv[3]);
-   mode = opus_custom_mode_create(rate, frame_size, NULL);
-   if (mode == NULL)
-   {
-      fprintf(stderr, "failed to create a mode\n");
-      return 1;
-   }
-
-   bytes_per_packet = atoi(argv[4]);
-   if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET)
-   {
-      fprintf (stderr, "bytes per packet must be between 0 and %d\n",
-                        MAX_PACKET);
-      return 1;
-   }
-
-   inFile = argv[argc-2];
-   fin = fopen(inFile, "rb");
-   if (!fin)
-   {
-      fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
-      return 1;
-   }
-   outFile = argv[argc-1];
-   fout = fopen(outFile, "wb+");
-   if (!fout)
-   {
-      fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
-      return 1;
-   }
-   
-   enc = opus_custom_encoder_create(mode, channels, &err);
-   if (err != 0)
-   {
-      fprintf(stderr, "Failed to create the encoder: %s\n", opus_strerror(err));
-      return 1;
-   }
-   dec = opus_custom_decoder_create(mode, channels, &err);
-   if (err != 0)
-   {
-      fprintf(stderr, "Failed to create the decoder: %s\n", opus_strerror(err));
-      return 1;
-   }
-   opus_custom_decoder_ctl(dec, CELT_GET_LOOKAHEAD(&skip));
-
-   if (argc>7)
-   {
-      complexity=atoi(argv[5]);
-      opus_custom_encoder_ctl(enc,CELT_SET_COMPLEXITY(complexity));
-   }
-   
-   in = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
-   out = (opus_int16*)malloc(frame_size*channels*sizeof(opus_int16));
-
-   while (!feof(fin))
-   {
-      int ret;
-      err = fread(in, sizeof(short), frame_size*channels, fin);
-      if (feof(fin))
-         break;
-      len = opus_custom_encode(enc, in, frame_size, data, bytes_per_packet);
-      if (len <= 0)
-         fprintf (stderr, "opus_custom_encode() failed: %s\n", opus_strerror(len));
-
-      /* This is for simulating bit errors */
-#if 0
-      int errors = 0;
-      int eid = 0;
-      /* This simulates random bit error */
-      for (i=0;i<len*8;i++)
-      {
-         if (rand()%atoi(argv[8])==0)
-         {
-            if (i<64)
-            {
-               errors++;
-               eid = i;
-            }
-            data[i/8] ^= 1<<(7-(i%8));
-         }
-      }
-      if (errors == 1)
-         data[eid/8] ^= 1<<(7-(eid%8));
-      else if (errors%2 == 1)
-         data[rand()%8] ^= 1<<rand()%8;
-#endif
-
-#if 1 /* Set to zero to use the encoder's output instead */
-      /* This is to simulate packet loss */
-      if (argc==9 && rand()%1000<atoi(argv[argc-3]))
-      /*if (errors && (errors%2==0))*/
-         ret = opus_custom_decode(dec, NULL, len, out, frame_size);
-      else
-         ret = opus_custom_decode(dec, data, len, out, frame_size);
-      if (ret < 0)
-         fprintf(stderr, "opus_custom_decode() failed: %s\n", opus_strerror(ret));
-#else
-      for (i=0;i<ret*channels;i++)
-         out[i] = in[i];
-#endif
-#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
-      for (i=0;i<ret*channels;i++)
-      {
-         rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
-         /*out[i] -= in[i];*/
-      }
-#endif
-      count++;
-      fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout);
-      skip = 0;
-   }
-   PRINT_MIPS(stderr);
-   
-   opus_custom_encoder_destroy(enc);
-   opus_custom_decoder_destroy(dec);
-   fclose(fin);
-   fclose(fout);
-   opus_custom_mode_destroy(mode);
-   free(in);
-   free(out);
-#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
-   if (rmsd > 0)
-   {
-      rmsd = sqrt(rmsd/(1.0*frame_size*channels*count));
-      fprintf (stderr, "Error: encoder doesn't match decoder\n");
-      fprintf (stderr, "RMS mismatch is %f\n", rmsd);
-      return 1;
-   } else {
-      fprintf (stderr, "Encoder matches decoder!!\n");
-   }
-#endif
-   return 0;
-}
-