aboutsummaryrefslogtreecommitdiffstats
path: root/codecs/G726/G726decode.c
diff options
context:
space:
mode:
Diffstat (limited to 'codecs/G726/G726decode.c')
-rw-r--r--codecs/G726/G726decode.c86
1 files changed, 61 insertions, 25 deletions
diff --git a/codecs/G726/G726decode.c b/codecs/G726/G726decode.c
index e454be5ac8..cb157d6c46 100644
--- a/codecs/G726/G726decode.c
+++ b/codecs/G726/G726decode.c
@@ -24,53 +24,89 @@
#include <glib.h>
#ifdef HAVE_SPANDSP
-#include "telephony.h"
-#include "bitstream.h"
-#include "g726.h"
+#include "spandsp.h"
#include "G726decode.h"
-/* this isn't reentrant. Making it might involve quite a few changes to be able to pass a g726 state
- * variable to the various functions involved in G.726 decoding.
- */
-static g726_state_t state;
+typedef struct _g726_codec_ctx {
+ g726_state_t *state;
+ int bit_rate;
+} g726_codec_ctx;
-/* Currently, only G.726-32, linear encoding, left packed is supported */
-void *
-codec_g726_init(void)
+static inline void *
+codec_g726_init(int bit_rate, int packing)
{
- memset (&state, 0, sizeof (state));
- g726_init(&state, 32000, 0, 1);
+ g726_state_t *decoder = g726_init(NULL, bit_rate, G726_ENCODING_LINEAR, packing);
+
+ if (!decoder) {
+ return NULL; /* out-of-memory; */
+ }
+
+ g726_codec_ctx *state = g_new(g726_codec_ctx, 1);
+ state->state = decoder;
+ state->bit_rate = bit_rate;
- return NULL;
+ return state;
}
+void *codec_g726_16_init(void) { return codec_g726_init(16000, G726_PACKING_RIGHT); }
+void *codec_g726_24_init(void) { return codec_g726_init(24000, G726_PACKING_RIGHT); }
+void *codec_g726_32_init(void) { return codec_g726_init(32000, G726_PACKING_RIGHT); }
+void *codec_g726_40_init(void) { return codec_g726_init(40000, G726_PACKING_RIGHT); }
+void *codec_aal2_g726_16_init(void) { return codec_g726_init(16000, G726_PACKING_LEFT); }
+void *codec_aal2_g726_24_init(void) { return codec_g726_init(24000, G726_PACKING_LEFT); }
+void *codec_aal2_g726_32_init(void) { return codec_g726_init(32000, G726_PACKING_LEFT); }
+void *codec_aal2_g726_40_init(void) { return codec_g726_init(40000, G726_PACKING_LEFT); }
+
void
-codec_g726_release(void *ctx _U_)
+codec_g726_release(void *ctx)
{
+ g726_codec_ctx *state = (g726_codec_ctx *)ctx;
+
+ if (!state) {
+ return; /* out-of-memory; */
+ }
+ /* Note: replaces g726_release since spandsp 20090211 */
+ g726_free(state->state);
+ g_free(state);
}
-int
+unsigned
codec_g726_get_channels(void *ctx _U_)
{
return 1;
}
-int
+unsigned
codec_g726_get_frequency(void *ctx _U_)
{
- return 32000;
+ return 8000;
}
-/* Packing should be user defined (via the decode dialog) since due to historical reasons two diverging
- * de facto standards are in use today (see RFC3551).
- */
-int
-codec_g726_decode(void *ctx _U_, const void *input, int inputSizeBytes, void *output,
- int *outputSizeBytes)
+size_t
+codec_g726_decode(void *ctx, const void *input, size_t inputSizeBytes, void *output,
+ size_t *outputSizeBytes)
{
- *outputSizeBytes = 2 * g726_decode(&state, output, (void*) input, inputSizeBytes);
- return 0;
+ g726_codec_ctx *state = (g726_codec_ctx *)ctx;
+
+ if (!state) {
+ return 0; /* out-of-memory; */
+ }
+
+ if (!output || !outputSizeBytes) {
+ /*
+ * sample rate 8kHz, for bitrate 16kHz we have 16/8 = 2 bits/sample, so
+ * 1 input byte (8 bits) will expand to four 16-bit samples. Likewise,
+ * for bitrate 40kHz we have 40/8 = 5 bits/sample. Alternatively:
+ * bitsPerSample = bitRate / sampleRate (8kHz).
+ * outputBytes = (inputBits / bitsPerSample) * sizeof(sample)
+ */
+ return inputSizeBytes * 8 / (state->bit_rate / 8000) * 2;
+ }
+
+ /* g726_decode returns the number of 16-bit samples. */
+ *outputSizeBytes = 2 * g726_decode(state->state, (int16_t *)output, (const uint8_t *) input, (int)inputSizeBytes);
+ return *outputSizeBytes;
}
#endif