shithub: opus

Download patch

ref: 24f36e0a95abe099545e0a660169f7c7fe083b63
parent: f1babf8e9c025bc55fef06812a6ba0585c8f6332
author: Jean-Marc Valin <[email protected]>
date: Tue Jul 6 10:41:20 EDT 2010

Adds a _ctl() control API to the encoder and decoder

--- a/src/hybrid.h
+++ b/src/hybrid.h
@@ -29,6 +29,50 @@
    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#ifndef HYBRID_H
+#define HYBRID_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_WIDEBAND      1101
+#define BANDWIDTH_SUPERWIDEBAND 1102
+#define BANDWIDTH_FULLBAND      1103
+
+
+
+#define HYBRID_SET_MODE_REQUEST 0
+#define HYBRID_SET_MODE(x) HYBRID_SET_MODE_REQUEST, __check_int(x)
+#define HYBRID_GET_MODE_REQUEST 1
+#define HYBRID_GET_MODE(x) HYBRID_GET_MODE_REQUEST, __check_int_ptr(x)
+
+#define HYBRID_SET_BANDWIDTH_REQUEST 2
+#define HYBRID_SET_BANDWIDTH(x) HYBRID_SET_BANDWIDTH_REQUEST, __check_int(x)
+#define HYBRID_GET_BANDWIDTH_REQUEST 3
+#define HYBRID_GET_BANDWIDTH(x) HYBRID_GET_BANDWIDTH_REQUEST, __check_int_ptr(x)
+
+#define HYBRID_SET_VBR_RATE_REQUEST 4
+#define HYBRID_SET_VBR_RATE(x) HYBRID_SET_VBR_RATE_REQUEST, __check_int(x)
+#define HYBRID_GET_VBR_RATE_REQUEST 5
+#define HYBRID_GET_VBR_RATE(x) HYBRID_GET_VBR_RATE_REQUEST, __check_int_ptr(x)
+
 typedef struct HybridEncoder HybridEncoder;
 typedef struct HybridDecoder HybridDecoder;
 
@@ -39,10 +83,19 @@
 
 void hybrid_encoder_destroy(HybridEncoder *st);
 
+void hybrid_encoder_ctl(HybridEncoder *st, int request, ...);
 
 HybridDecoder *hybrid_decoder_create();
+
 int hybrid_decode(HybridDecoder *st, const unsigned char *data, int len,
 		short *pcm, int frame_size);
 
+void hybrid_decoder_ctl(HybridDecoder *st, int request, ...);
+
 void hybrid_decoder_destroy(HybridDecoder *st);
 
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HYBRID_H */
--- a/src/hybrid_decoder.c
+++ b/src/hybrid_decoder.c
@@ -35,6 +35,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdarg.h>
 #include "hybrid_decoder.h"
 #include "celt/libcelt/entdec.h"
 #include "celt/libcelt/modes.h"
@@ -72,7 +73,7 @@
 int hybrid_decode(HybridDecoder *st, const unsigned char *data,
 		int len, short *pcm, int frame_size)
 {
-	int i, silk_ret, celt_ret;
+	int i, silk_ret=0, celt_ret=0;
 	ec_dec dec;
 	ec_byte_buffer buf;
     SKP_SILK_SDK_DecControlStruct DecControl;
@@ -82,25 +83,76 @@
 	ec_byte_readinit(&buf,(unsigned char*)data,len);
 	ec_dec_init(&dec,&buf);
 
-	DecControl.API_sampleRate = 48000;
-	/* Call SILK encoder for the low band */
-	silk_ret = SKP_Silk_SDK_Decode( st->silk_dec, &DecControl, 0, &dec, len, pcm, &silk_frame_size );
-	if (silk_ret)
-	{
-		fprintf (stderr, "SILK decode error\n");
-		/* Handle error */
-	}
+    if (st->mode != MODE_CELT_ONLY)
+    {
+        DecControl.API_sampleRate = 48000;
+        /* Call SILK encoder for the low band */
+        silk_ret = SKP_Silk_SDK_Decode( st->silk_dec, &DecControl, 0, &dec, len, pcm, &silk_frame_size );
+        if (silk_ret)
+        {
+            fprintf (stderr, "SILK decode error\n");
+            /* Handle error */
+        }
+    } else {
+        for (i=0;i<960;i++)
+            pcm[i] = 0;
+    }
 
-	/* This should be adjusted based on the SILK bandwidth */
-	celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(13));
+    if (st->mode == MODE_HYBRID)
+    {
+        /* This should be adjusted based on the SILK bandwidth */
+        celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(13));
+    } else {
+        celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(0));
+    }
 
-	/* 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<960;i++)
-		pcm[i] += pcm_celt[i];
-
+    if (st->mode != MODE_SILK_ONLY)
+    {
+        /* 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<960;i++)
+            pcm[i] += pcm_celt[i];
+    }
 	return celt_ret;
 
+}
+
+void hybrid_decoder_ctl(HybridDecoder *st, int request, ...)
+{
+    va_list ap;
+
+    va_start(ap, request);
+
+    switch (request)
+    {
+        case HYBRID_SET_MODE_REQUEST:
+        {
+            int value = va_arg(ap, int);
+            st->mode = value;
+        }
+        break;
+        case HYBRID_GET_MODE_REQUEST:
+        {
+            int *value = va_arg(ap, int*);
+            *value = st->mode;
+        }
+        break;
+        case HYBRID_SET_BANDWIDTH_REQUEST:
+        {
+            int value = va_arg(ap, int);
+            st->bandwidth = value;
+        }
+        break;
+        case HYBRID_GET_BANDWIDTH_REQUEST:
+        {
+            int *value = va_arg(ap, int*);
+            *value = st->bandwidth;
+        }
+        break;
+        default:
+            fprintf(stderr, "unknown hybrid_decoder_ctl() request: %d", request);
+            break;
+    }
 }
 
 void hybrid_decoder_destroy(HybridDecoder *st)
--- a/src/hybrid_decoder.h
+++ b/src/hybrid_decoder.h
@@ -39,6 +39,9 @@
 	CELTMode    *celt_mode;
 	CELTDecoder *celt_dec;
 	void        *silk_dec;
+
+    int          mode;
+    int          bandwidth;
 };
 
 
--- a/src/hybrid_encoder.c
+++ b/src/hybrid_encoder.c
@@ -35,6 +35,7 @@
 
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdarg.h>
 #include "hybrid_encoder.h"
 #include "celt/libcelt/entenc.h"
 #include "celt/libcelt/modes.h"
@@ -74,6 +75,9 @@
 	/* Initialize CELT encoder */
 	st->celt_enc = celt_encoder_create(st->celt_mode, 1, NULL);
 
+	st->mode = MODE_HYBRID;
+	st->bandwidth = BANDWIDTH_FULLBAND;
+
 	return st;
 }
 
@@ -80,7 +84,7 @@
 int hybrid_encode(HybridEncoder *st, const short *pcm, int frame_size,
 		unsigned char *data, int bytes_per_packet)
 {
-	int silk_ret, celt_ret;
+	int ret=0;
 	SKP_int16 nBytes;
 	ec_enc enc;
 	ec_byte_buffer buf;
@@ -88,24 +92,87 @@
 	ec_byte_writeinit_buffer(&buf, data, bytes_per_packet);
 	ec_enc_init(&enc,&buf);
 
-    st->encControl.bitRate               = (bytes_per_packet*50*8+4000)/2;
+	if (st->mode != MODE_CELT_ONLY)
+	{
+	    st->encControl.bitRate               = (bytes_per_packet*50*8+4000)/2;
+	    /* Call SILK encoder for the low band */
+	    nBytes = bytes_per_packet;
+	    ret = SKP_Silk_SDK_Encode( st->silk_enc, &st->encControl, pcm, 960, &enc, &nBytes );
+	    if( ret ) {
+	        fprintf (stderr, "SILK encode error\n");
+	        /* Handle error */
+	    }
+	    ret = (ec_enc_tell(&enc, 0)+7)>>3;
+	}
 
-	/* Call SILK encoder for the low band */
-    nBytes = bytes_per_packet;
-	silk_ret = SKP_Silk_SDK_Encode( st->silk_enc, &st->encControl, pcm, 960, &enc, &nBytes );
-    if( silk_ret ) {
-    	fprintf (stderr, "SILK encode error\n");
-        /* Handle error */
-    }
+	if (st->mode == MODE_HYBRID)
+	{
+	    /* This should be adjusted based on the SILK bandwidth */
+	    celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(13));
+	} else {
+        celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(0));
+	}
 
-	/* This should be adjusted based on the SILK bandwidth */
-	celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(13));
+	if (st->mode != MODE_SILK_ONLY)
+	{
+	    /* Encode high band with CELT */
+	    /* FIXME: Do some delay compensation here */
+	    ret = celt_encode_with_ec(st->celt_enc, pcm, NULL, frame_size, data, bytes_per_packet, &enc);
+	} else {
+	    ec_enc_done(&enc);
+	}
 
-	/* Encode high band with CELT */
-	/* FIXME: Do some delay compensation here */
-	celt_ret = celt_encode_with_ec(st->celt_enc, pcm, NULL, frame_size, data, bytes_per_packet, &enc);
+	return ret;
+}
 
-	return celt_ret;
+void hybrid_encoder_ctl(HybridEncoder *st, int request, ...)
+{
+    va_list ap;
+
+    va_start(ap, request);
+
+    switch (request)
+    {
+        case HYBRID_SET_MODE_REQUEST:
+        {
+            int value = va_arg(ap, int);
+            st->mode = value;
+        }
+        break;
+        case HYBRID_GET_MODE_REQUEST:
+        {
+            int *value = va_arg(ap, int*);
+            *value = st->mode;
+        }
+        break;
+        case HYBRID_SET_BANDWIDTH_REQUEST:
+        {
+            int value = va_arg(ap, int);
+            st->bandwidth = value;
+        }
+        break;
+        case HYBRID_GET_BANDWIDTH_REQUEST:
+        {
+            int *value = va_arg(ap, int*);
+            *value = st->bandwidth;
+        }
+        break;
+        case HYBRID_SET_VBR_RATE_REQUEST:
+        {
+            int value = va_arg(ap, int);
+            st->vbr_rate = value;
+        }
+        break;
+        case HYBRID_GET_VBR_RATE_REQUEST:
+        {
+            int *value = va_arg(ap, int*);
+            *value = st->vbr_rate;
+        }
+        break;
+        default:
+            fprintf(stderr, "unknown hybrid_encoder_ctl() request: %d", request);
+            break;
+    }
 }
 
 void hybrid_encoder_destroy(HybridEncoder *st)
@@ -117,3 +184,4 @@
 
 	free(st);
 }
+
--- a/src/hybrid_encoder.h
+++ b/src/hybrid_encoder.h
@@ -41,6 +41,10 @@
 	CELTEncoder *celt_enc;
 	void        *silk_enc;
 	SKP_SILK_SDK_EncControlStruct encControl;
+
+    int          mode;
+	int          bandwidth;
+    int          vbr_rate;
 };
 
 
--- a/src/test_hybrid.c
+++ b/src/test_hybrid.c
@@ -58,6 +58,7 @@
    int count = 0;
    int skip;
    short *in, *out;
+   int mode=MODE_HYBRID;
    if (argc != 9 && argc != 8 && argc != 7)
    {
       fprintf (stderr, "Usage: test_hybrid <rate> <channels> <frame size> "
@@ -95,6 +96,13 @@
 
    enc = hybrid_encoder_create();
    dec = hybrid_decoder_create();
+
+   mode = MODE_HYBRID;
+   hybrid_encoder_ctl(enc, HYBRID_SET_BANDWIDTH(BANDWIDTH_FULLBAND));
+   hybrid_encoder_ctl(enc, HYBRID_SET_MODE(mode));
+
+   hybrid_decoder_ctl(dec, HYBRID_SET_BANDWIDTH(BANDWIDTH_FULLBAND));
+   hybrid_decoder_ctl(dec, HYBRID_SET_MODE(mode));
 
    in = (short*)malloc(frame_size*channels*sizeof(short));
    out = (short*)malloc(frame_size*channels*sizeof(short));