shithub: opus

Download patch

ref: 05dd36a1b36670b1eb9d8f510ad1aa82944ac091
parent: 4e777532ee8acccf62cdf62d8efc4c3f4c6a3104
author: Jean-Marc Valin <[email protected]>
date: Mon Oct 18 08:50:49 EDT 2010

API renamed to Opus

--- a/README
+++ b/README
@@ -23,10 +23,10 @@
 % make
 
 
-Once you have compiled the codec, there will be a test_harmony executable in
+Once you have compiled the codec, there will be a test_opus executable in
 the src/ directory. This can be in the following way:
 
-% ./test_harmony 48000 1 960 80 input.sw output.sw
+% ./test_opus 48000 1 960 80 input.sw output.sw
 
 The arguments are:
 1) The sampling rate (only 48000 supported for now)
--- a/configure.ac
+++ b/configure.ac
@@ -2,8 +2,8 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ([2.59])
-AC_INIT(src/harmony.h)
-AM_INIT_AUTOMAKE(harmony,20100921)
+AC_INIT(src/opus.h)
+AM_INIT_AUTOMAKE(opus,20100921)
 
 # Checks for programs.
 AC_PROG_CC
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,12 +2,12 @@
 INCLUDES = -I$(top_srcdir)/celt/libcelt/ -I$(top_srcdir)/silk/interface 
 
 lib_LTLIBRARIES = libietfcodec.la
-libietfcodec_la_SOURCES = harmony_decoder.c harmony_encoder.c
+libietfcodec_la_SOURCES = opus_decoder.c opus_encoder.c
 
-noinst_HEADERS = harmony_decoder.h harmony_encoder.h
+noinst_HEADERS = opus_decoder.h opus_encoder.h
 
-pkginclude_HEADERS = harmony.h
+pkginclude_HEADERS = opus.h
 
-noinst_PROGRAMS = test_harmony
-test_harmony_SOURCES = test_harmony.c $(top_srcdir)/silk/test/SKP_debug.c
-test_harmony_LDADD = libietfcodec.la $(top_builddir)/celt/libcelt/libcelt0.la $(top_builddir)/silk/libSKP_SILK_SDK.la
+noinst_PROGRAMS = test_opus
+test_opus_SOURCES = test_opus.c $(top_srcdir)/silk/test/SKP_debug.c
+test_opus_LDADD = libietfcodec.la $(top_builddir)/celt/libcelt/libcelt0.la $(top_builddir)/silk/libSKP_SILK_SDK.la
--- a/src/framepack.c
+++ b/src/framepack.c
@@ -100,7 +100,7 @@
 }
 
 #define MAX_FRAMES 256
-int harmony_merge_packets(unsigned char **packets, int *plen, int nb_packets,
+int opus_merge_packets(unsigned char **packets, int *plen, int nb_packets,
         unsigned *output, int maxlen)
 {
     int i;
--- a/src/harmony.h
+++ /dev/null
@@ -1,102 +1,0 @@
-/* Copyright (c) 2010 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.
-
-   - Neither the name of the Xiph.org Foundation nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-   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 HARMONY_H
-#define HARMONY_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(__GNUC__) && defined(CELT_BUILD)
-#define EXPORT __attribute__ ((visibility ("default")))
-#elif defined(WIN32)
-#define EXPORT __declspec(dllexport)
-#else
-#define EXPORT
-#endif
-
-#define __check_int(x) (((void)((x) == (int)0)), (int)(x))
-#define __check_int_ptr(ptr) ((ptr) + ((ptr) - (int*)(ptr)))
-
-#define MODE_SILK_ONLY 1000
-#define MODE_HYBRID    1001
-#define MODE_CELT_ONLY 1002
-
-#define BANDWIDTH_NARROWBAND    1100
-#define BANDWIDTH_MEDIUMBAND    1101
-#define BANDWIDTH_WIDEBAND      1102
-#define BANDWIDTH_SUPERWIDEBAND 1103
-#define BANDWIDTH_FULLBAND      1104
-
-
-
-#define HARMONY_SET_MODE_REQUEST 0
-#define HARMONY_SET_MODE(x) HARMONY_SET_MODE_REQUEST, __check_int(x)
-#define HARMONY_GET_MODE_REQUEST 1
-#define HARMONY_GET_MODE(x) HARMONY_GET_MODE_REQUEST, __check_int_ptr(x)
-
-#define HARMONY_SET_BANDWIDTH_REQUEST 2
-#define HARMONY_SET_BANDWIDTH(x) HARMONY_SET_BANDWIDTH_REQUEST, __check_int(x)
-#define HARMONY_GET_BANDWIDTH_REQUEST 3
-#define HARMONY_GET_BANDWIDTH(x) HARMONY_GET_BANDWIDTH_REQUEST, __check_int_ptr(x)
-
-#define HARMONY_SET_VBR_RATE_REQUEST 4
-#define HARMONY_SET_VBR_RATE(x) HARMONY_SET_VBR_RATE_REQUEST, __check_int(x)
-#define HARMONY_GET_VBR_RATE_REQUEST 5
-#define HARMONY_GET_VBR_RATE(x) HARMONY_GET_VBR_RATE_REQUEST, __check_int_ptr(x)
-
-typedef struct HarmonyEncoder HarmonyEncoder;
-typedef struct HarmonyDecoder HarmonyDecoder;
-
-HarmonyEncoder *harmony_encoder_create(int Fs);
-
-int harmony_encode(HarmonyEncoder *st, const short *pcm, int frame_size,
-		unsigned char *data, int bytes_per_packet);
-
-void harmony_encoder_destroy(HarmonyEncoder *st);
-
-void harmony_encoder_ctl(HarmonyEncoder *st, int request, ...);
-
-HarmonyDecoder *harmony_decoder_create(int Fs);
-
-int harmony_decode(HarmonyDecoder *st, const unsigned char *data, int len,
-		short *pcm, int frame_size);
-
-void harmony_decoder_ctl(HarmonyDecoder *st, int request, ...);
-
-void harmony_decoder_destroy(HarmonyDecoder *st);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* HARMONY_H */
--- a/src/harmony_decoder.c
+++ /dev/null
@@ -1,212 +1,0 @@
-/* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
-   Written by Jean-Marc Valin and Koen Vos */
-/*
-   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.
-
-   - Neither the name of the Xiph.org Foundation nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-   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 <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include "harmony_decoder.h"
-#include "entdec.h"
-#include "modes.h"
-#include "SKP_Silk_SDK_API.h"
-
-
-HarmonyDecoder *harmony_decoder_create(int Fs)
-{
-    char *raw_state;
-	int ret, silkDecSizeBytes, celtDecSizeBytes;
-	CELTMode *celtMode;
-	HarmonyDecoder *st;
-
-    /* We should not have to create a CELT mode for each encoder state */
-    celtMode = celt_mode_create(Fs, Fs/50, NULL);
-
-	/* Initialize SILK encoder */
-    ret = SKP_Silk_SDK_Get_Decoder_Size( &silkDecSizeBytes );
-    if( ret ) {
-        /* Handle error */
-    }
-    celtDecSizeBytes = celt_decoder_get_size(celtMode, 1);
-    raw_state = calloc(sizeof(HarmonyDecoder)+silkDecSizeBytes+celtDecSizeBytes, 1);
-    st = (HarmonyDecoder*)raw_state;
-    st->silk_dec = (void*)(raw_state+sizeof(HarmonyDecoder));
-    st->celt_dec = (CELTDecoder*)(raw_state+sizeof(HarmonyDecoder)+silkDecSizeBytes);
-
-    st->Fs = Fs;
-    st->celt_mode = celtMode;
-
-    /* Reset decoder */
-    ret = SKP_Silk_SDK_InitDecoder( st->silk_dec );
-    if( ret ) {
-        /* Handle error */
-    }
-
-	/* Initialize CELT decoder */
-	st->celt_dec = celt_decoder_init(st->celt_dec, st->celt_mode, 1, NULL);
-
-	return st;
-
-}
-int harmony_decode(HarmonyDecoder *st, const unsigned char *data,
-		int len, short *pcm, int frame_size)
-{
-	int i, silk_ret=0, celt_ret=0;
-	ec_dec dec;
-	ec_byte_buffer buf;
-    SKP_SILK_SDK_DecControlStruct DecControl;
-    SKP_int16 silk_frame_size;
-    short pcm_celt[960];
-    int audiosize;
-
-    if (data != NULL)
-    {
-        /* Decoding mode/bandwidth/framesize from first byte */
-        if (data[0]&0x80)
-        {
-            st->mode = MODE_CELT_ONLY;
-            st->bandwidth = BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3);
-            if (st->bandwidth == BANDWIDTH_MEDIUMBAND)
-                st->bandwidth = BANDWIDTH_NARROWBAND;
-            audiosize = ((data[0]>>3)&0x3);
-            audiosize = (st->Fs<<audiosize)/400;
-        } else if ((data[0]&0x60) == 0x60)
-        {
-            st->mode = MODE_HYBRID;
-            st->bandwidth = (data[0]&0x10) ? BANDWIDTH_FULLBAND : BANDWIDTH_SUPERWIDEBAND;
-            audiosize = (data[0]&0x08) ? st->Fs/50 : st->Fs/100;
-        } else {
-
-            st->mode = MODE_SILK_ONLY;
-            st->bandwidth = BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3);
-            audiosize = ((data[0]>>3)&0x3);
-            if (audiosize == 3)
-                audiosize = st->Fs*60/1000;
-            else
-                audiosize = (st->Fs<<audiosize)/100;
-        }
-        /*printf ("%d %d %d\n", st->mode, st->bandwidth, audiosize);*/
-
-        len -= 1;
-        data += 1;
-        ec_byte_readinit(&buf,(unsigned char*)data,len);
-        ec_dec_init(&dec,&buf);
-    }
-
-    if (st->mode != MODE_CELT_ONLY)
-    {
-        DecControl.API_sampleRate = st->Fs;
-
-        /* We Should eventually have to set the bandwidth here */
-
-        /* Call SILK encoder for the low band */
-        silk_ret = SKP_Silk_SDK_Decode( st->silk_dec, &DecControl, data == NULL, &dec, len, pcm, &silk_frame_size );
-        if (silk_ret)
-        {
-            fprintf (stderr, "SILK decode error\n");
-            /* Handle error */
-        }
-    } else {
-        for (i=0;i<frame_size;i++)
-            pcm[i] = 0;
-    }
-
-    if (st->mode == MODE_HYBRID)
-    {
-        /* This should be adjusted based on the SILK bandwidth */
-        celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(17));
-    } else {
-        celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(0));
-    }
-
-    if (st->mode != MODE_SILK_ONLY && st->bandwidth > BANDWIDTH_WIDEBAND)
-    {
-        if (st->bandwidth == BANDWIDTH_SUPERWIDEBAND)
-            celt_decoder_ctl(st->celt_dec, CELT_SET_END_BAND(20));
-        else
-            celt_decoder_ctl(st->celt_dec, CELT_SET_END_BAND(21));
-        /* Encode high band with CELT */
-        celt_ret = celt_decode_with_ec(st->celt_dec, data, len, pcm_celt, frame_size, &dec);
-        for (i=0;i<frame_size;i++)
-            pcm[i] += pcm_celt[i];
-    }
-	return celt_ret;
-
-}
-
-void harmony_decoder_ctl(HarmonyDecoder *st, int request, ...)
-{
-    va_list ap;
-
-    va_start(ap, request);
-
-    switch (request)
-    {
-        case HARMONY_SET_MODE_REQUEST:
-        {
-            int value = va_arg(ap, int);
-            st->mode = value;
-        }
-        break;
-        case HARMONY_GET_MODE_REQUEST:
-        {
-            int *value = va_arg(ap, int*);
-            *value = st->mode;
-        }
-        break;
-        case HARMONY_SET_BANDWIDTH_REQUEST:
-        {
-            int value = va_arg(ap, int);
-            st->bandwidth = value;
-        }
-        break;
-        case HARMONY_GET_BANDWIDTH_REQUEST:
-        {
-            int *value = va_arg(ap, int*);
-            *value = st->bandwidth;
-        }
-        break;
-        default:
-            fprintf(stderr, "unknown harmony_decoder_ctl() request: %d", request);
-            break;
-    }
-
-    va_end(ap);
-}
-
-void harmony_decoder_destroy(HarmonyDecoder *st)
-{
-	celt_mode_destroy(st->celt_mode);
-
-	free(st);
-}
--- a/src/harmony_decoder.h
+++ /dev/null
@@ -1,51 +1,0 @@
-/* Copyright (c) 2010 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.
-
-   - Neither the name of the Xiph.org Foundation nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-   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 HARMONY_DECODER_H
-#define HARMONY_DECODER_H
-
-#include "celt.h"
-#include "harmony.h"
-
-struct HarmonyDecoder {
-	CELTMode    *celt_mode;
-	CELTDecoder *celt_dec;
-	void        *silk_dec;
-
-    int          mode;
-    int          bandwidth;
-    /* Sampling rate (at the API level) */
-    int          Fs;
-};
-
-
-#endif /* HARMONY_DECODER_H */
-
--- a/src/harmony_encoder.c
+++ /dev/null
@@ -1,270 +1,0 @@
-/* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
-   Written by Jean-Marc Valin and Koen Vos */
-/*
-   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.
-
-   - Neither the name of the Xiph.org Foundation nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-   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 <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include "harmony_encoder.h"
-#include "entenc.h"
-#include "modes.h"
-#include "SKP_Silk_SDK_API.h"
-
-HarmonyEncoder *harmony_encoder_create(int Fs)
-{
-    char *raw_state;
-    CELTMode *celtMode;
-	HarmonyEncoder *st;
-	int ret, silkEncSizeBytes, celtEncSizeBytes;
-    SKP_SILK_SDK_EncControlStruct encControl;
-
-    /* We should not have to create a CELT mode for each encoder state */
-    celtMode = celt_mode_create(Fs, Fs/50, NULL);
-
-    /* Create SILK encoder */
-    ret = SKP_Silk_SDK_Get_Encoder_Size( &silkEncSizeBytes );
-    if( ret ) {
-    	/* Handle error */
-    }
-    celtEncSizeBytes = celt_encoder_get_size(celtMode, 1);
-    raw_state = calloc(sizeof(HarmonyEncoder)+silkEncSizeBytes+celtEncSizeBytes, 1);
-    st = (HarmonyEncoder*)raw_state;
-    st->silk_enc = (void*)(raw_state+sizeof(HarmonyEncoder));
-    st->celt_enc = (CELTEncoder*)(raw_state+sizeof(HarmonyEncoder)+silkEncSizeBytes);
-
-    st->Fs = Fs;
-    st->celt_mode = celtMode;
-
-    /*encControl.API_sampleRate        = st->Fs;
-    encControl.packetLossPercentage  = 0;
-    encControl.useInBandFEC          = 0;
-    encControl.useDTX                = 0;
-    encControl.complexity            = 2;*/
-    ret = SKP_Silk_SDK_InitEncoder( st->silk_enc, &encControl );
-    if( ret ) {
-        /* Handle error */
-    }
-
-    /* Create CELT encoder */
-	/* Initialize CELT encoder */
-	st->celt_enc = celt_encoder_init(st->celt_enc, st->celt_mode, 1, NULL);
-
-	st->mode = MODE_HYBRID;
-	st->bandwidth = BANDWIDTH_FULLBAND;
-	st->vbr_rate = 0;
-
-	return st;
-}
-
-int harmony_encode(HarmonyEncoder *st, const short *pcm, int frame_size,
-		unsigned char *data, int bytes_per_packet)
-{
-    int i;
-	int ret=0;
-	SKP_int16 nBytes;
-	ec_enc enc;
-	ec_byte_buffer buf;
-	SKP_SILK_SDK_EncControlStruct encControl;
-	int framerate, period;
-
-	bytes_per_packet -= 1;
-	data += 1;
-	ec_byte_writeinit_buffer(&buf, data, bytes_per_packet);
-	ec_enc_init(&enc,&buf);
-
-	if (st->mode != MODE_CELT_ONLY)
-	{
-	    /* Set Encoder parameters */
-	    encControl.API_sampleRate        = st->Fs;
-	    encControl.packetLossPercentage  = 2;
-	    encControl.useInBandFEC          = 0;
-	    encControl.useDTX                = 0;
-	    encControl.complexity            = 2;
-
-	    if (st->vbr_rate != 0)
-            encControl.bitRate = (st->vbr_rate+6000)/2;
-	    else {
-	        encControl.bitRate = (bytes_per_packet*8*(celt_int32)st->Fs/frame_size+6000)/2;
-	        if (st->Fs  == 100 * frame_size)
-	            encControl.bitRate -= 5000;
-	    }
-	    encControl.packetSize = frame_size;
-
-	    if (st->bandwidth == BANDWIDTH_NARROWBAND)
-	        encControl.maxInternalSampleRate = 8000;
-	    else if (st->bandwidth == BANDWIDTH_MEDIUMBAND)
-            encControl.maxInternalSampleRate = 12000;
-	    else
-	        encControl.maxInternalSampleRate = 16000;
-
-	    /* Call SILK encoder for the low band */
-	    nBytes = bytes_per_packet;
-	    ret = SKP_Silk_SDK_Encode( st->silk_enc, &encControl, pcm, frame_size, &enc, &nBytes );
-	    if( ret ) {
-	        fprintf (stderr, "SILK encode error\n");
-	        /* Handle error */
-	    }
-	    ret = (ec_enc_tell(&enc, 0)+7)>>3;
-	}
-
-	if (st->mode == MODE_HYBRID)
-	{
-	    /* This should be adjusted based on the SILK bandwidth */
-	    celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(17));
-	} else {
-        celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
-	}
-
-	if (st->mode != MODE_SILK_ONLY && st->bandwidth > BANDWIDTH_WIDEBAND)
-	{
-	    short pcm_buf[960];
-
-        if (st->bandwidth == BANDWIDTH_SUPERWIDEBAND)
-            celt_encoder_ctl(st->celt_enc, CELT_SET_END_BAND(20));
-        else
-            celt_encoder_ctl(st->celt_enc, CELT_SET_END_BAND(21));
-
-	    for (i=0;i<ENCODER_DELAY_COMPENSATION;i++)
-	        pcm_buf[i] = st->delay_buffer[i];
-        for (;i<frame_size;i++)
-            pcm_buf[i] = pcm[i-ENCODER_DELAY_COMPENSATION];
-
-        celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(1));
-
-        if (st->vbr_rate != 0)
-        {
-            int tmp = (st->vbr_rate-6000)/2;
-            tmp = ((ec_enc_tell(&enc, 0)+4)>>3) + tmp * frame_size/(8*st->Fs);
-            if (tmp <= bytes_per_packet)
-                bytes_per_packet = tmp;
-            ec_byte_shrink(&buf, bytes_per_packet);
-        }
-	    /* Encode high band with CELT */
-	    ret = celt_encode_with_ec(st->celt_enc, pcm_buf, NULL, frame_size, NULL, bytes_per_packet, &enc);
-	    for (i=0;i<ENCODER_DELAY_COMPENSATION;i++)
-	        st->delay_buffer[i] = pcm[frame_size-ENCODER_DELAY_COMPENSATION+i];
-	} else {
-	    ec_enc_done(&enc);
-	}
-
-	/* Signalling the mode in the first byte */
-	data--;
-	framerate = st->Fs/frame_size;
-	period = 0;
-	while (framerate < 400)
-	{
-	    framerate <<= 1;
-	    period++;
-	}
-    if (st->mode == MODE_SILK_ONLY)
-    {
-        data[0] = (st->bandwidth-BANDWIDTH_NARROWBAND)<<5;
-        data[0] |= (period-2)<<3;
-    } else if (st->mode == MODE_CELT_ONLY)
-    {
-        int tmp = st->bandwidth-BANDWIDTH_MEDIUMBAND;
-        if (tmp < 0)
-            tmp = 0;
-        data[0] = 0x80;
-        data[0] |= tmp << 5;
-        data[0] |= period<<3;
-    } else /* Harmony */
-    {
-        data[0] = 0x60;
-        data[0] |= (st->bandwidth-BANDWIDTH_SUPERWIDEBAND)<<4;
-        data[0] |= (period-2)<<3;
-    }
-    /*printf ("%x\n", (int)data[0]);*/
-
-    return ret+1;
-}
-
-void harmony_encoder_ctl(HarmonyEncoder *st, int request, ...)
-{
-    va_list ap;
-
-    va_start(ap, request);
-
-    switch (request)
-    {
-        case HARMONY_SET_MODE_REQUEST:
-        {
-            int value = va_arg(ap, int);
-            st->mode = value;
-        }
-        break;
-        case HARMONY_GET_MODE_REQUEST:
-        {
-            int *value = va_arg(ap, int*);
-            *value = st->mode;
-        }
-        break;
-        case HARMONY_SET_BANDWIDTH_REQUEST:
-        {
-            int value = va_arg(ap, int);
-            st->bandwidth = value;
-        }
-        break;
-        case HARMONY_GET_BANDWIDTH_REQUEST:
-        {
-            int *value = va_arg(ap, int*);
-            *value = st->bandwidth;
-        }
-        break;
-        case HARMONY_SET_VBR_RATE_REQUEST:
-        {
-            int value = va_arg(ap, int);
-            st->vbr_rate = value;
-        }
-        break;
-        case HARMONY_GET_VBR_RATE_REQUEST:
-        {
-            int *value = va_arg(ap, int*);
-            *value = st->vbr_rate;
-        }
-        break;
-        default:
-            fprintf(stderr, "unknown harmony_encoder_ctl() request: %d", request);
-            break;
-    }
-
-    va_end(ap);
-}
-
-void harmony_encoder_destroy(HarmonyEncoder *st)
-{
-	celt_mode_destroy(st->celt_mode);
-	free(st);
-}
-
--- a/src/harmony_encoder.h
+++ /dev/null
@@ -1,58 +1,0 @@
-/* Copyright (c) 2010 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.
-
-   - Neither the name of the Xiph.org Foundation nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-   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 HARMONY_ENCODER_H
-#define HARMONY_ENCODER_H
-
-#include "celt.h"
-#include "harmony.h"
-#include "SKP_Silk_SDK_API.h"
-
-/* FIXME: This is only valid for 48 kHz */
-#define ENCODER_DELAY_COMPENSATION 130
-
-struct HarmonyEncoder {
-	CELTMode    *celt_mode;
-	CELTEncoder *celt_enc;
-	void        *silk_enc;
-
-    int          mode;
-	int          bandwidth;
-    int          vbr_rate;
-    /* Sampling rate (at the API level) */
-    int          Fs;
-
-    short        delay_buffer[ENCODER_DELAY_COMPENSATION];
-};
-
-
-#endif /* HARMONY_ENCODER_H */
-
--- /dev/null
+++ b/src/opus.h
@@ -1,0 +1,102 @@
+/* Copyright (c) 2010 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.
+
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   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_H
+#define OPUS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(__GNUC__) && defined(CELT_BUILD)
+#define EXPORT __attribute__ ((visibility ("default")))
+#elif defined(WIN32)
+#define EXPORT __declspec(dllexport)
+#else
+#define EXPORT
+#endif
+
+#define __check_int(x) (((void)((x) == (int)0)), (int)(x))
+#define __check_int_ptr(ptr) ((ptr) + ((ptr) - (int*)(ptr)))
+
+#define MODE_SILK_ONLY 1000
+#define MODE_HYBRID    1001
+#define MODE_CELT_ONLY 1002
+
+#define BANDWIDTH_NARROWBAND    1100
+#define BANDWIDTH_MEDIUMBAND    1101
+#define BANDWIDTH_WIDEBAND      1102
+#define BANDWIDTH_SUPERWIDEBAND 1103
+#define BANDWIDTH_FULLBAND      1104
+
+
+
+#define OPUS_SET_MODE_REQUEST 0
+#define OPUS_SET_MODE(x) OPUS_SET_MODE_REQUEST, __check_int(x)
+#define OPUS_GET_MODE_REQUEST 1
+#define OPUS_GET_MODE(x) OPUS_GET_MODE_REQUEST, __check_int_ptr(x)
+
+#define OPUS_SET_BANDWIDTH_REQUEST 2
+#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __check_int(x)
+#define OPUS_GET_BANDWIDTH_REQUEST 3
+#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __check_int_ptr(x)
+
+#define OPUS_SET_VBR_RATE_REQUEST 4
+#define OPUS_SET_VBR_RATE(x) OPUS_SET_VBR_RATE_REQUEST, __check_int(x)
+#define OPUS_GET_VBR_RATE_REQUEST 5
+#define OPUS_GET_VBR_RATE(x) OPUS_GET_VBR_RATE_REQUEST, __check_int_ptr(x)
+
+typedef struct OpusEncoder OpusEncoder;
+typedef struct OpusDecoder OpusDecoder;
+
+OpusEncoder *opus_encoder_create(int Fs);
+
+int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
+		unsigned char *data, int bytes_per_packet);
+
+void opus_encoder_destroy(OpusEncoder *st);
+
+void opus_encoder_ctl(OpusEncoder *st, int request, ...);
+
+OpusDecoder *opus_decoder_create(int Fs);
+
+int opus_decode(OpusDecoder *st, const unsigned char *data, int len,
+		short *pcm, int frame_size);
+
+void opus_decoder_ctl(OpusDecoder *st, int request, ...);
+
+void opus_decoder_destroy(OpusDecoder *st);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPUS_H */
--- /dev/null
+++ b/src/opus_decoder.c
@@ -1,0 +1,212 @@
+/* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
+   Written by Jean-Marc Valin and Koen Vos */
+/*
+   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.
+
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   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 <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "opus_decoder.h"
+#include "entdec.h"
+#include "modes.h"
+#include "SKP_Silk_SDK_API.h"
+
+
+OpusDecoder *opus_decoder_create(int Fs)
+{
+    char *raw_state;
+	int ret, silkDecSizeBytes, celtDecSizeBytes;
+	CELTMode *celtMode;
+	OpusDecoder *st;
+
+    /* We should not have to create a CELT mode for each encoder state */
+    celtMode = celt_mode_create(Fs, Fs/50, NULL);
+
+	/* Initialize SILK encoder */
+    ret = SKP_Silk_SDK_Get_Decoder_Size( &silkDecSizeBytes );
+    if( ret ) {
+        /* Handle error */
+    }
+    celtDecSizeBytes = celt_decoder_get_size(celtMode, 1);
+    raw_state = calloc(sizeof(OpusDecoder)+silkDecSizeBytes+celtDecSizeBytes, 1);
+    st = (OpusDecoder*)raw_state;
+    st->silk_dec = (void*)(raw_state+sizeof(OpusDecoder));
+    st->celt_dec = (CELTDecoder*)(raw_state+sizeof(OpusDecoder)+silkDecSizeBytes);
+
+    st->Fs = Fs;
+    st->celt_mode = celtMode;
+
+    /* Reset decoder */
+    ret = SKP_Silk_SDK_InitDecoder( st->silk_dec );
+    if( ret ) {
+        /* Handle error */
+    }
+
+	/* Initialize CELT decoder */
+	st->celt_dec = celt_decoder_init(st->celt_dec, st->celt_mode, 1, NULL);
+
+	return st;
+
+}
+int opus_decode(OpusDecoder *st, const unsigned char *data,
+		int len, short *pcm, int frame_size)
+{
+	int i, silk_ret=0, celt_ret=0;
+	ec_dec dec;
+	ec_byte_buffer buf;
+    SKP_SILK_SDK_DecControlStruct DecControl;
+    SKP_int16 silk_frame_size;
+    short pcm_celt[960];
+    int audiosize;
+
+    if (data != NULL)
+    {
+        /* Decoding mode/bandwidth/framesize from first byte */
+        if (data[0]&0x80)
+        {
+            st->mode = MODE_CELT_ONLY;
+            st->bandwidth = BANDWIDTH_MEDIUMBAND + ((data[0]>>5)&0x3);
+            if (st->bandwidth == BANDWIDTH_MEDIUMBAND)
+                st->bandwidth = BANDWIDTH_NARROWBAND;
+            audiosize = ((data[0]>>3)&0x3);
+            audiosize = (st->Fs<<audiosize)/400;
+        } else if ((data[0]&0x60) == 0x60)
+        {
+            st->mode = MODE_HYBRID;
+            st->bandwidth = (data[0]&0x10) ? BANDWIDTH_FULLBAND : BANDWIDTH_SUPERWIDEBAND;
+            audiosize = (data[0]&0x08) ? st->Fs/50 : st->Fs/100;
+        } else {
+
+            st->mode = MODE_SILK_ONLY;
+            st->bandwidth = BANDWIDTH_NARROWBAND + ((data[0]>>5)&0x3);
+            audiosize = ((data[0]>>3)&0x3);
+            if (audiosize == 3)
+                audiosize = st->Fs*60/1000;
+            else
+                audiosize = (st->Fs<<audiosize)/100;
+        }
+        /*printf ("%d %d %d\n", st->mode, st->bandwidth, audiosize);*/
+
+        len -= 1;
+        data += 1;
+        ec_byte_readinit(&buf,(unsigned char*)data,len);
+        ec_dec_init(&dec,&buf);
+    }
+
+    if (st->mode != MODE_CELT_ONLY)
+    {
+        DecControl.API_sampleRate = st->Fs;
+
+        /* We Should eventually have to set the bandwidth here */
+
+        /* Call SILK encoder for the low band */
+        silk_ret = SKP_Silk_SDK_Decode( st->silk_dec, &DecControl, data == NULL, &dec, len, pcm, &silk_frame_size );
+        if (silk_ret)
+        {
+            fprintf (stderr, "SILK decode error\n");
+            /* Handle error */
+        }
+    } else {
+        for (i=0;i<frame_size;i++)
+            pcm[i] = 0;
+    }
+
+    if (st->mode == MODE_HYBRID)
+    {
+        /* This should be adjusted based on the SILK bandwidth */
+        celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(17));
+    } else {
+        celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(0));
+    }
+
+    if (st->mode != MODE_SILK_ONLY && st->bandwidth > BANDWIDTH_WIDEBAND)
+    {
+        if (st->bandwidth == BANDWIDTH_SUPERWIDEBAND)
+            celt_decoder_ctl(st->celt_dec, CELT_SET_END_BAND(20));
+        else
+            celt_decoder_ctl(st->celt_dec, CELT_SET_END_BAND(21));
+        /* Encode high band with CELT */
+        celt_ret = celt_decode_with_ec(st->celt_dec, data, len, pcm_celt, frame_size, &dec);
+        for (i=0;i<frame_size;i++)
+            pcm[i] += pcm_celt[i];
+    }
+	return celt_ret;
+
+}
+
+void opus_decoder_ctl(OpusDecoder *st, int request, ...)
+{
+    va_list ap;
+
+    va_start(ap, request);
+
+    switch (request)
+    {
+        case OPUS_SET_MODE_REQUEST:
+        {
+            int value = va_arg(ap, int);
+            st->mode = value;
+        }
+        break;
+        case OPUS_GET_MODE_REQUEST:
+        {
+            int *value = va_arg(ap, int*);
+            *value = st->mode;
+        }
+        break;
+        case OPUS_SET_BANDWIDTH_REQUEST:
+        {
+            int value = va_arg(ap, int);
+            st->bandwidth = value;
+        }
+        break;
+        case OPUS_GET_BANDWIDTH_REQUEST:
+        {
+            int *value = va_arg(ap, int*);
+            *value = st->bandwidth;
+        }
+        break;
+        default:
+            fprintf(stderr, "unknown opus_decoder_ctl() request: %d", request);
+            break;
+    }
+
+    va_end(ap);
+}
+
+void opus_decoder_destroy(OpusDecoder *st)
+{
+	celt_mode_destroy(st->celt_mode);
+
+	free(st);
+}
--- /dev/null
+++ b/src/opus_decoder.h
@@ -1,0 +1,51 @@
+/* Copyright (c) 2010 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.
+
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   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_DECODER_H
+#define OPUS_DECODER_H
+
+#include "celt.h"
+#include "opus.h"
+
+struct OpusDecoder {
+	CELTMode    *celt_mode;
+	CELTDecoder *celt_dec;
+	void        *silk_dec;
+
+    int          mode;
+    int          bandwidth;
+    /* Sampling rate (at the API level) */
+    int          Fs;
+};
+
+
+#endif /* OPUS_DECODER_H */
+
--- /dev/null
+++ b/src/opus_encoder.c
@@ -1,0 +1,270 @@
+/* Copyright (c) 2010 Xiph.Org Foundation, Skype Limited
+   Written by Jean-Marc Valin and Koen Vos */
+/*
+   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.
+
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   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 <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "opus_encoder.h"
+#include "entenc.h"
+#include "modes.h"
+#include "SKP_Silk_SDK_API.h"
+
+OpusEncoder *opus_encoder_create(int Fs)
+{
+    char *raw_state;
+    CELTMode *celtMode;
+	OpusEncoder *st;
+	int ret, silkEncSizeBytes, celtEncSizeBytes;
+    SKP_SILK_SDK_EncControlStruct encControl;
+
+    /* We should not have to create a CELT mode for each encoder state */
+    celtMode = celt_mode_create(Fs, Fs/50, NULL);
+
+    /* Create SILK encoder */
+    ret = SKP_Silk_SDK_Get_Encoder_Size( &silkEncSizeBytes );
+    if( ret ) {
+    	/* Handle error */
+    }
+    celtEncSizeBytes = celt_encoder_get_size(celtMode, 1);
+    raw_state = calloc(sizeof(OpusEncoder)+silkEncSizeBytes+celtEncSizeBytes, 1);
+    st = (OpusEncoder*)raw_state;
+    st->silk_enc = (void*)(raw_state+sizeof(OpusEncoder));
+    st->celt_enc = (CELTEncoder*)(raw_state+sizeof(OpusEncoder)+silkEncSizeBytes);
+
+    st->Fs = Fs;
+    st->celt_mode = celtMode;
+
+    /*encControl.API_sampleRate        = st->Fs;
+    encControl.packetLossPercentage  = 0;
+    encControl.useInBandFEC          = 0;
+    encControl.useDTX                = 0;
+    encControl.complexity            = 2;*/
+    ret = SKP_Silk_SDK_InitEncoder( st->silk_enc, &encControl );
+    if( ret ) {
+        /* Handle error */
+    }
+
+    /* Create CELT encoder */
+	/* Initialize CELT encoder */
+	st->celt_enc = celt_encoder_init(st->celt_enc, st->celt_mode, 1, NULL);
+
+	st->mode = MODE_HYBRID;
+	st->bandwidth = BANDWIDTH_FULLBAND;
+	st->vbr_rate = 0;
+
+	return st;
+}
+
+int opus_encode(OpusEncoder *st, const short *pcm, int frame_size,
+		unsigned char *data, int bytes_per_packet)
+{
+    int i;
+	int ret=0;
+	SKP_int16 nBytes;
+	ec_enc enc;
+	ec_byte_buffer buf;
+	SKP_SILK_SDK_EncControlStruct encControl;
+	int framerate, period;
+
+	bytes_per_packet -= 1;
+	data += 1;
+	ec_byte_writeinit_buffer(&buf, data, bytes_per_packet);
+	ec_enc_init(&enc,&buf);
+
+	if (st->mode != MODE_CELT_ONLY)
+	{
+	    /* Set Encoder parameters */
+	    encControl.API_sampleRate        = st->Fs;
+	    encControl.packetLossPercentage  = 2;
+	    encControl.useInBandFEC          = 0;
+	    encControl.useDTX                = 0;
+	    encControl.complexity            = 2;
+
+	    if (st->vbr_rate != 0)
+            encControl.bitRate = (st->vbr_rate+6000)/2;
+	    else {
+	        encControl.bitRate = (bytes_per_packet*8*(celt_int32)st->Fs/frame_size+6000)/2;
+	        if (st->Fs  == 100 * frame_size)
+	            encControl.bitRate -= 5000;
+	    }
+	    encControl.packetSize = frame_size;
+
+	    if (st->bandwidth == BANDWIDTH_NARROWBAND)
+	        encControl.maxInternalSampleRate = 8000;
+	    else if (st->bandwidth == BANDWIDTH_MEDIUMBAND)
+            encControl.maxInternalSampleRate = 12000;
+	    else
+	        encControl.maxInternalSampleRate = 16000;
+
+	    /* Call SILK encoder for the low band */
+	    nBytes = bytes_per_packet;
+	    ret = SKP_Silk_SDK_Encode( st->silk_enc, &encControl, pcm, frame_size, &enc, &nBytes );
+	    if( ret ) {
+	        fprintf (stderr, "SILK encode error\n");
+	        /* Handle error */
+	    }
+	    ret = (ec_enc_tell(&enc, 0)+7)>>3;
+	}
+
+	if (st->mode == MODE_HYBRID)
+	{
+	    /* This should be adjusted based on the SILK bandwidth */
+	    celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(17));
+	} else {
+        celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
+	}
+
+	if (st->mode != MODE_SILK_ONLY && st->bandwidth > BANDWIDTH_WIDEBAND)
+	{
+	    short pcm_buf[960];
+
+        if (st->bandwidth == BANDWIDTH_SUPERWIDEBAND)
+            celt_encoder_ctl(st->celt_enc, CELT_SET_END_BAND(20));
+        else
+            celt_encoder_ctl(st->celt_enc, CELT_SET_END_BAND(21));
+
+	    for (i=0;i<ENCODER_DELAY_COMPENSATION;i++)
+	        pcm_buf[i] = st->delay_buffer[i];
+        for (;i<frame_size;i++)
+            pcm_buf[i] = pcm[i-ENCODER_DELAY_COMPENSATION];
+
+        celt_encoder_ctl(st->celt_enc, CELT_SET_PREDICTION(1));
+
+        if (st->vbr_rate != 0)
+        {
+            int tmp = (st->vbr_rate-6000)/2;
+            tmp = ((ec_enc_tell(&enc, 0)+4)>>3) + tmp * frame_size/(8*st->Fs);
+            if (tmp <= bytes_per_packet)
+                bytes_per_packet = tmp;
+            ec_byte_shrink(&buf, bytes_per_packet);
+        }
+	    /* Encode high band with CELT */
+	    ret = celt_encode_with_ec(st->celt_enc, pcm_buf, NULL, frame_size, NULL, bytes_per_packet, &enc);
+	    for (i=0;i<ENCODER_DELAY_COMPENSATION;i++)
+	        st->delay_buffer[i] = pcm[frame_size-ENCODER_DELAY_COMPENSATION+i];
+	} else {
+	    ec_enc_done(&enc);
+	}
+
+	/* Signalling the mode in the first byte */
+	data--;
+	framerate = st->Fs/frame_size;
+	period = 0;
+	while (framerate < 400)
+	{
+	    framerate <<= 1;
+	    period++;
+	}
+    if (st->mode == MODE_SILK_ONLY)
+    {
+        data[0] = (st->bandwidth-BANDWIDTH_NARROWBAND)<<5;
+        data[0] |= (period-2)<<3;
+    } else if (st->mode == MODE_CELT_ONLY)
+    {
+        int tmp = st->bandwidth-BANDWIDTH_MEDIUMBAND;
+        if (tmp < 0)
+            tmp = 0;
+        data[0] = 0x80;
+        data[0] |= tmp << 5;
+        data[0] |= period<<3;
+    } else /* Opus */
+    {
+        data[0] = 0x60;
+        data[0] |= (st->bandwidth-BANDWIDTH_SUPERWIDEBAND)<<4;
+        data[0] |= (period-2)<<3;
+    }
+    /*printf ("%x\n", (int)data[0]);*/
+
+    return ret+1;
+}
+
+void opus_encoder_ctl(OpusEncoder *st, int request, ...)
+{
+    va_list ap;
+
+    va_start(ap, request);
+
+    switch (request)
+    {
+        case OPUS_SET_MODE_REQUEST:
+        {
+            int value = va_arg(ap, int);
+            st->mode = value;
+        }
+        break;
+        case OPUS_GET_MODE_REQUEST:
+        {
+            int *value = va_arg(ap, int*);
+            *value = st->mode;
+        }
+        break;
+        case OPUS_SET_BANDWIDTH_REQUEST:
+        {
+            int value = va_arg(ap, int);
+            st->bandwidth = value;
+        }
+        break;
+        case OPUS_GET_BANDWIDTH_REQUEST:
+        {
+            int *value = va_arg(ap, int*);
+            *value = st->bandwidth;
+        }
+        break;
+        case OPUS_SET_VBR_RATE_REQUEST:
+        {
+            int value = va_arg(ap, int);
+            st->vbr_rate = value;
+        }
+        break;
+        case OPUS_GET_VBR_RATE_REQUEST:
+        {
+            int *value = va_arg(ap, int*);
+            *value = st->vbr_rate;
+        }
+        break;
+        default:
+            fprintf(stderr, "unknown opus_encoder_ctl() request: %d", request);
+            break;
+    }
+
+    va_end(ap);
+}
+
+void opus_encoder_destroy(OpusEncoder *st)
+{
+	celt_mode_destroy(st->celt_mode);
+	free(st);
+}
+
--- /dev/null
+++ b/src/opus_encoder.h
@@ -1,0 +1,58 @@
+/* Copyright (c) 2010 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.
+
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   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_ENCODER_H
+#define OPUS_ENCODER_H
+
+#include "celt.h"
+#include "opus.h"
+#include "SKP_Silk_SDK_API.h"
+
+/* FIXME: This is only valid for 48 kHz */
+#define ENCODER_DELAY_COMPENSATION 130
+
+struct OpusEncoder {
+	CELTMode    *celt_mode;
+	CELTEncoder *celt_enc;
+	void        *silk_enc;
+
+    int          mode;
+	int          bandwidth;
+    int          vbr_rate;
+    /* Sampling rate (at the API level) */
+    int          Fs;
+
+    short        delay_buffer[ENCODER_DELAY_COMPENSATION];
+};
+
+
+#endif /* OPUS_ENCODER_H */
+
--- a/src/test_harmony.c
+++ /dev/null
@@ -1,160 +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.
-
-   - Neither the name of the Xiph.org Foundation nor the names of its
-   contributors may be used to endorse or promote products derived from
-   this software without specific prior written permission.
-
-   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 <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-#include <string.h>
-#include "harmony.h"
-
-
-#define MAX_PACKET 1024
-
-int main(int argc, char *argv[])
-{
-   int err;
-   char *inFile, *outFile;
-   FILE *fin, *fout;
-   HarmonyEncoder *enc;
-   HarmonyDecoder *dec;
-   int len;
-   int frame_size, channels;
-   int bytes_per_packet;
-   unsigned char data[MAX_PACKET];
-   int rate;
-   int loss = 0;
-   int count = 0;
-   int skip;
-   int stop=0;
-   int vbr=0;
-   int tot_read=0, tot_written=0;
-   short *in, *out;
-   int mode=MODE_HYBRID;
-   double bits=0;
-   if (argc != 9 && argc != 8 && argc != 7)
-   {
-      fprintf (stderr, "Usage: test_harmony <rate (kHz)> <channels> <frame size> "
-               " <bytes per packet>  [<VBR rate (kb/s)>] [<packet loss rate>] "
-               "<input> <output>\n");
-      return 1;
-   }
-
-   rate = atoi(argv[1]);
-   channels = atoi(argv[2]);
-   frame_size = atoi(argv[3]);
-
-   bytes_per_packet = atoi(argv[4]);
-
-   if (argc >= 8)
-       vbr = atoi(argv[5]);
-   if (argc >= 9)
-       loss = atoi(argv[6]);
-
-   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 = harmony_encoder_create(rate);
-   dec = harmony_decoder_create(rate);
-
-   mode = MODE_HYBRID;
-   harmony_encoder_ctl(enc, HARMONY_SET_BANDWIDTH(BANDWIDTH_FULLBAND));
-   harmony_encoder_ctl(enc, HARMONY_SET_MODE(mode));
-
-   if (vbr)
-       harmony_encoder_ctl(enc, HARMONY_SET_VBR_RATE(vbr));
-
-   skip = 5*rate/1000 + 10;
-
-   in = (short*)malloc(frame_size*channels*sizeof(short));
-   out = (short*)malloc(frame_size*channels*sizeof(short));
-   while (!stop)
-   {
-      int write_samples;
-      err = fread(in, sizeof(short), frame_size*channels, fin);
-      tot_read += err;
-      if (err < frame_size*channels)
-      {
-          int i;
-          for (i=err;i<frame_size*channels;i++)
-              in[i] = 0;
-      }
-      len = harmony_encode(enc, in, frame_size, data, bytes_per_packet);
-      if (len <= 0)
-      {
-         fprintf (stderr, "harmony_encode() returned %d\n", len);
-         return 1;
-      }
-      bits += len*8;
-      harmony_decode(dec, rand()%100<loss ? NULL : data, len, out, frame_size);
-      count++;
-      tot_written += (frame_size-skip)*channels;
-      write_samples = frame_size;
-      if (tot_written > tot_read && skip==0)
-      {
-          write_samples -= (tot_written-tot_read)/channels;
-          stop = 1;
-      }
-      fwrite(out+skip, sizeof(short), (write_samples-skip)*channels, fout);
-      skip = 0;
-   }
-   fprintf (stderr, "average bit-rate: %f kb/s\n", bits*rate/(frame_size*(double)count));
-   harmony_encoder_destroy(enc);
-   harmony_decoder_destroy(dec);
-   fclose(fin);
-   fclose(fout);
-   free(in);
-   free(out);
-   return 0;
-}
--- /dev/null
+++ b/src/test_opus.c
@@ -1,0 +1,160 @@
+/* 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.
+
+   - Neither the name of the Xiph.org Foundation nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   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 <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <string.h>
+#include "opus.h"
+
+
+#define MAX_PACKET 1024
+
+int main(int argc, char *argv[])
+{
+   int err;
+   char *inFile, *outFile;
+   FILE *fin, *fout;
+   OpusEncoder *enc;
+   OpusDecoder *dec;
+   int len;
+   int frame_size, channels;
+   int bytes_per_packet;
+   unsigned char data[MAX_PACKET];
+   int rate;
+   int loss = 0;
+   int count = 0;
+   int skip;
+   int stop=0;
+   int vbr=0;
+   int tot_read=0, tot_written=0;
+   short *in, *out;
+   int mode=MODE_HYBRID;
+   double bits=0;
+   if (argc != 9 && argc != 8 && argc != 7)
+   {
+      fprintf (stderr, "Usage: test_opus <rate (kHz)> <channels> <frame size> "
+               " <bytes per packet>  [<VBR rate (kb/s)>] [<packet loss rate>] "
+               "<input> <output>\n");
+      return 1;
+   }
+
+   rate = atoi(argv[1]);
+   channels = atoi(argv[2]);
+   frame_size = atoi(argv[3]);
+
+   bytes_per_packet = atoi(argv[4]);
+
+   if (argc >= 8)
+       vbr = atoi(argv[5]);
+   if (argc >= 9)
+       loss = atoi(argv[6]);
+
+   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_encoder_create(rate);
+   dec = opus_decoder_create(rate);
+
+   mode = MODE_HYBRID;
+   opus_encoder_ctl(enc, OPUS_SET_BANDWIDTH(BANDWIDTH_FULLBAND));
+   opus_encoder_ctl(enc, OPUS_SET_MODE(mode));
+
+   if (vbr)
+       opus_encoder_ctl(enc, OPUS_SET_VBR_RATE(vbr));
+
+   skip = 5*rate/1000 + 10;
+
+   in = (short*)malloc(frame_size*channels*sizeof(short));
+   out = (short*)malloc(frame_size*channels*sizeof(short));
+   while (!stop)
+   {
+      int write_samples;
+      err = fread(in, sizeof(short), frame_size*channels, fin);
+      tot_read += err;
+      if (err < frame_size*channels)
+      {
+          int i;
+          for (i=err;i<frame_size*channels;i++)
+              in[i] = 0;
+      }
+      len = opus_encode(enc, in, frame_size, data, bytes_per_packet);
+      if (len <= 0)
+      {
+         fprintf (stderr, "opus_encode() returned %d\n", len);
+         return 1;
+      }
+      bits += len*8;
+      opus_decode(dec, rand()%100<loss ? NULL : data, len, out, frame_size);
+      count++;
+      tot_written += (frame_size-skip)*channels;
+      write_samples = frame_size;
+      if (tot_written > tot_read && skip==0)
+      {
+          write_samples -= (tot_written-tot_read)/channels;
+          stop = 1;
+      }
+      fwrite(out+skip, sizeof(short), (write_samples-skip)*channels, fout);
+      skip = 0;
+   }
+   fprintf (stderr, "average bit-rate: %f kb/s\n", bits*rate/(frame_size*(double)count));
+   opus_encoder_destroy(enc);
+   opus_decoder_destroy(dec);
+   fclose(fin);
+   fclose(fout);
+   free(in);
+   free(out);
+   return 0;
+}