Adds a _ctl() control API to the encoder and decoder
authorJean-Marc Valin <jean-marc.valin@octasic.com>
Tue, 6 Jul 2010 18:41:20 +0000 (14:41 -0400)
committerJean-Marc Valin <jean-marc.valin@octasic.com>
Tue, 6 Jul 2010 18:41:20 +0000 (14:41 -0400)
silk
src/hybrid.h
src/hybrid_decoder.c
src/hybrid_decoder.h
src/hybrid_encoder.c
src/hybrid_encoder.h
src/test_hybrid.c

diff --git a/silk b/silk
index 6f9a028..130e02e 160000 (submodule)
--- a/silk
+++ b/silk
@@ -1 +1 @@
-Subproject commit 6f9a028cad836b8f41f479d244be849fc16e48b8
+Subproject commit 130e02e2c494769231337746745849dddbd48f7b
index ae03293..94d9f06 100644 (file)
    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 @@ int hybrid_encode(HybridEncoder *st, const short *pcm, int frame_size,
 
 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 */
index fae32fb..0bece75 100644 (file)
@@ -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 @@ HybridDecoder *hybrid_decoder_create()
 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,27 +83,78 @@ int hybrid_decode(HybridDecoder *st, const unsigned char *data,
        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 */
-       }
-
-       /* This should be adjusted based on the SILK bandwidth */
-       celt_decoder_ctl(st->celt_dec, CELT_SET_START_BAND(13));
+    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;
+    }
 
-       /* 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_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));
+    }
 
+    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)
 {
        free(st->silk_dec);
index 85a7b21..180c32a 100644 (file)
@@ -39,6 +39,9 @@ struct HybridDecoder {
        CELTMode    *celt_mode;
        CELTDecoder *celt_dec;
        void        *silk_dec;
+
+    int          mode;
+    int          bandwidth;
 };
 
 
index 900204a..881ef09 100644 (file)
@@ -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,13 +75,16 @@ HybridEncoder *hybrid_encoder_create()
        /* Initialize CELT encoder */
        st->celt_enc = celt_encoder_create(st->celt_mode, 1, NULL);
 
+       st->mode = MODE_HYBRID;
+       st->bandwidth = BANDWIDTH_FULLBAND;
+
        return st;
 }
 
 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 @@ int hybrid_encode(HybridEncoder *st, const short *pcm, int frame_size,
        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;
+       }
+
+       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));
+       }
+
+       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);
+       }
+
+       return ret;
+}
 
-       /* 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 */
+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;
     }
-
-       /* This should be adjusted based on the SILK bandwidth */
-       celt_encoder_ctl(st->celt_enc, CELT_SET_START_BAND(13));
-
-       /* 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 celt_ret;
 }
 
 void hybrid_encoder_destroy(HybridEncoder *st)
@@ -117,3 +184,4 @@ void hybrid_encoder_destroy(HybridEncoder *st)
 
        free(st);
 }
+
index 8d8269c..66ef4db 100644 (file)
@@ -41,6 +41,10 @@ struct HybridEncoder {
        CELTEncoder *celt_enc;
        void        *silk_enc;
        SKP_SILK_SDK_EncControlStruct encControl;
+
+    int          mode;
+       int          bandwidth;
+    int          vbr_rate;
 };
 
 
index ed6a6b6..06ae843 100644 (file)
@@ -58,6 +58,7 @@ int main(int argc, char *argv[])
    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> "
@@ -96,6 +97,13 @@ int main(int argc, char *argv[])
    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));
    while (!feof(fin))