Add GSM HR reference codec that is automatically downloaded from 3gpp.org
[lcr.git] / libgsmhr / libgsmhr.c
diff --git a/libgsmhr/libgsmhr.c b/libgsmhr/libgsmhr.c
new file mode 100644 (file)
index 0000000..d018c90
--- /dev/null
@@ -0,0 +1,111 @@
+/* HR (GSM 06.20) codec wrapper */
+
+/*
+ * This file is part of gapk (GSM Audio Pocket Knife).
+ *
+ * gapk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * gapk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gapk.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gsmhr/gsmhr.h>
+
+#include "refsrc/typedefs.h"
+#include "refsrc/homing.h"
+#include "refsrc/sp_dec.h"
+#include "refsrc/sp_enc.h"
+
+
+#define EXPORT __attribute__((visibility("default")))
+
+
+struct gsmhr {
+       int dec_reset_flg;
+};
+
+EXPORT struct gsmhr *
+gsmhr_init(void)
+{
+       struct gsmhr *state;
+
+       state = calloc(1, sizeof(struct gsmhr));
+       if (!state)
+               return NULL;
+
+       state->dec_reset_flg = 1;
+
+       return state;
+}
+
+EXPORT void
+gsmhr_exit(struct gsmhr *state)
+{
+       free(state);
+}
+
+EXPORT int
+gsmhr_encode(struct gsmhr *state, int16_t *hr_params, const int16_t *pcm)
+{
+       int enc_reset_flg;
+       Shortword pcm_b[F_LEN];
+
+       memcpy(pcm_b, pcm, F_LEN*sizeof(int16_t));
+
+       enc_reset_flg = encoderHomingFrameTest(pcm_b);
+
+       speechEncoder(pcm_b, hr_params);
+
+       if (enc_reset_flg)
+               resetEnc();
+
+       return 0;
+}
+
+EXPORT int
+gsmhr_decode(struct gsmhr *state, int16_t *pcm, const int16_t *hr_params)
+{
+#define WHOLE_FRAME            18
+#define TO_FIRST_SUBFRAME       9
+
+       int dec_reset_flg;
+       Shortword hr_params_b[22];
+
+       memcpy(hr_params_b, hr_params, 22*sizeof(int16_t));
+
+       if (state->dec_reset_flg)
+               dec_reset_flg = decoderHomingFrameTest(hr_params_b, TO_FIRST_SUBFRAME);
+       else
+               dec_reset_flg = 0;
+
+       if (dec_reset_flg && state->dec_reset_flg) {
+               int i;
+               for (i=0; i<F_LEN; i++)
+                       pcm[i] = EHF_MASK;
+       } else {
+               speechDecoder(hr_params_b, pcm);
+       }
+
+       if (!state->dec_reset_flg)
+               dec_reset_flg = decoderHomingFrameTest(hr_params_b, WHOLE_FRAME);
+
+       if (dec_reset_flg)
+               resetDec();
+
+       state->dec_reset_flg = dec_reset_flg;
+
+       return 0;
+}