diff options
author | Jean-Marc Valin <jean-marc.valin@octasic.com> | 2010-07-06 22:41:20 +0400 |
---|---|---|
committer | Jean-Marc Valin <jean-marc.valin@octasic.com> | 2010-07-06 22:41:20 +0400 |
commit | 24f36e0a95abe099545e0a660169f7c7fe083b63 (patch) | |
tree | 233b98b00222a3f8baff5b70dc42ba86cdc6a0b1 | |
parent | f1babf8e9c025bc55fef06812a6ba0585c8f6332 (diff) |
Adds a _ctl() control API to the encoder and decoder
m--------- | silk | 10 | ||||
-rw-r--r-- | src/hybrid.h | 53 | ||||
-rw-r--r-- | src/hybrid_decoder.c | 84 | ||||
-rw-r--r-- | src/hybrid_decoder.h | 3 | ||||
-rw-r--r-- | src/hybrid_encoder.c | 102 | ||||
-rw-r--r-- | src/hybrid_encoder.h | 4 | ||||
-rw-r--r-- | src/test_hybrid.c | 8 |
7 files changed, 226 insertions, 38 deletions
diff --git a/silk b/silk -Subproject 6f9a028cad836b8f41f479d244be849fc16e48b +Subproject 130e02e2c494769231337746745849dddbd48f7 diff --git a/src/hybrid.h b/src/hybrid.h index ae03293b..94d9f063 100644 --- 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 @@ 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 */ diff --git a/src/hybrid_decoder.c b/src/hybrid_decoder.c index fae32fb9..0bece75c 100644 --- 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 @@ 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); diff --git a/src/hybrid_decoder.h b/src/hybrid_decoder.h index 85a7b21e..180c32a3 100644 --- a/src/hybrid_decoder.h +++ b/src/hybrid_decoder.h @@ -39,6 +39,9 @@ struct HybridDecoder { CELTMode *celt_mode; CELTDecoder *celt_dec; void *silk_dec; + + int mode; + int bandwidth; }; diff --git a/src/hybrid_encoder.c b/src/hybrid_encoder.c index 900204ad..881ef09c 100644 --- 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,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); } + diff --git a/src/hybrid_encoder.h b/src/hybrid_encoder.h index 8d8269c3..66ef4dbe 100644 --- a/src/hybrid_encoder.h +++ b/src/hybrid_encoder.h @@ -41,6 +41,10 @@ struct HybridEncoder { CELTEncoder *celt_enc; void *silk_enc; SKP_SILK_SDK_EncControlStruct encControl; + + int mode; + int bandwidth; + int vbr_rate; }; diff --git a/src/test_hybrid.c b/src/test_hybrid.c index ed6a6b69..06ae8438 100644 --- a/src/test_hybrid.c +++ b/src/test_hybrid.c @@ -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)) |