encoder.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*
  2. * ===================================================================
  3. * TS 26.104
  4. * REL-5 V5.4.0 2004-03
  5. * REL-6 V6.1.0 2004-03
  6. * REL-15 V15.1.0 2018-07
  7. * 3GPP AMR Floating-point Speech Codec
  8. * ===================================================================
  9. *
  10. */
  11. /*
  12. * encoder.c
  13. *
  14. *
  15. * Project:
  16. * AMR Floating-Point Codec
  17. *
  18. * Contains:
  19. * Speech encoder main program
  20. *
  21. */
  22. #include <stdlib.h>
  23. #include <stdio.h>
  24. #include <string.h>
  25. #include "typedef.h"
  26. #include "interf_enc.h"
  27. #include "board.h"
  28. #ifndef ETSI
  29. #ifndef IF2
  30. #define AMR_MAGIC_NUMBER "#!AMR\n"
  31. #endif
  32. #endif
  33. #define PATH_STRING_MAX_LEN 256
  34. #define MODE_MAX_LEN 10
  35. static char file_speech_path[PATH_STRING_MAX_LEN];
  36. static char file_encoded_path[PATH_STRING_MAX_LEN];
  37. static char file_mode_path[MODE_MAX_LEN];
  38. static const short modeConv[] = {475, 515, 59, 67, 74, 795, 102, 122};
  39. static void EncoderUsage(void)
  40. {
  41. rt_kprintf("Usage: encoder -dtx [mode] [speech_file] [bitstream_file]\n");
  42. rt_kprintf(" mode : MR475, MR515, MR59, MR67, MR74, MR795, MR102, MR122\n");
  43. rt_kprintf(" example : encoder -dtx MR102 test.wav out.amr\n");
  44. }
  45. static void EncoderCopyright(void)
  46. {
  47. rt_kprintf("Copyright:\n");
  48. rt_kprintf("========================================\n");
  49. rt_kprintf(" TS 26.104 \n");
  50. rt_kprintf(" REL-16 V16.0.0 2018-09 \n");
  51. rt_kprintf(" 3GPP AMR Floating-point Speech Encoder \n");
  52. rt_kprintf("========================================\n");
  53. }
  54. /*
  55. * main
  56. *
  57. *
  58. * Function:
  59. * Speech encoder main program
  60. *
  61. * Usage: encoder speech_file bitstream_file mode dtx mode_file
  62. *
  63. * Format for speech_file:
  64. * Speech is read from a binary file of 16 bits data.
  65. *
  66. * Format for ETSI bitstream file:
  67. * 1 word (2-byte) for the TX frame type
  68. * 244 words (2-byte) containing 244 bits.
  69. * Bit 0 = 0x0000 and Bit 1 = 0x0001
  70. * 1 word (2-byte) for the mode indication
  71. * 4 words for future use, currently written as zero
  72. *
  73. * Format for 3GPP bitstream file:
  74. * Holds mode information and bits packed to octets.
  75. * Size is from 1 byte to 31 bytes.
  76. *
  77. * ETSI bitstream file format is defined using ETSI as preprocessor
  78. * definition
  79. *
  80. * mode : MR475, MR515, MR59, MR67, MR74, MR795, MR102, MR122
  81. * mode_file : reads mode information from a file
  82. * Returns:
  83. * 0
  84. */
  85. static void encoder_thread(void *parameter)
  86. {
  87. /* file strucrures */
  88. FILE *file_speech = NULL;
  89. FILE *file_encoded = NULL;
  90. FILE *file_mode = NULL;
  91. /* input speech vector */
  92. short speech[160];
  93. /* counters */
  94. int byte_counter, frames = 0, bytes = 0;
  95. /* pointer to encoder state structure */
  96. int *enstate;
  97. /* requested mode */
  98. enum Mode req_mode = MR122;
  99. int dtx = 0;
  100. /* temporary variables */
  101. char mode_string[9];
  102. long mode_tmp;
  103. /* bitstream filetype */
  104. #ifndef ETSI
  105. unsigned char serial_data[32];
  106. #else
  107. short serial_data[250] =
  108. {0};
  109. #endif
  110. /* Process command line options */
  111. rt_tick_t tick = rt_tick_get_millisecond();
  112. // open encoded file
  113. file_encoded = fopen(file_encoded_path, "wb");
  114. if (file_encoded == NULL)
  115. {
  116. rt_kprintf("open encoded file '%s' error !\n", file_encoded_path);
  117. return;
  118. }
  119. // open speech file
  120. file_speech = fopen(file_speech_path, "rb");
  121. if (file_speech == NULL)
  122. {
  123. rt_kprintf("open speech file '%s' error !\n", file_speech_path);
  124. fclose(file_encoded);
  125. return;
  126. }
  127. // set code rate
  128. mode_tmp = strtol(&file_mode_path[2], NULL, 0);
  129. for (req_mode = 0; req_mode < 8; req_mode++)
  130. {
  131. if (mode_tmp == modeConv[req_mode])
  132. break;
  133. }
  134. if (req_mode == 8)
  135. {
  136. rt_kprintf("mode error !\n");
  137. fclose(file_speech);
  138. fclose(file_encoded);
  139. if (file_mode != NULL)
  140. fclose(file_mode);
  141. return;
  142. }
  143. dtx = 1;
  144. enstate = Encoder_Interface_init(dtx);
  145. EncoderCopyright();
  146. #ifndef VAD2
  147. rt_kprintf("%s\n", "Code compiled with VAD option: VAD1");
  148. #else
  149. rt_kprintf("%s\n", "Code compiled with VAD option: VAD2");
  150. #endif
  151. #ifndef ETSI
  152. #ifndef IF2
  153. /* write magic number to indicate single channel AMR file storage format */
  154. bytes = fwrite(AMR_MAGIC_NUMBER, sizeof(char), strlen(AMR_MAGIC_NUMBER), file_encoded);
  155. #endif
  156. #endif
  157. /* read file */
  158. while (fread(speech, sizeof(Word16), 160, file_speech) > 0)
  159. {
  160. /* read mode */
  161. if (file_mode != NULL)
  162. {
  163. req_mode = 8;
  164. if (fscanf(file_mode, "%9s\n", mode_string) != EOF)
  165. {
  166. mode_tmp = strtol(&mode_string[2], NULL, 0);
  167. for (req_mode = 0; req_mode < 8; req_mode++)
  168. {
  169. if (mode_tmp == modeConv[req_mode])
  170. {
  171. break;
  172. }
  173. }
  174. }
  175. if (req_mode == 8)
  176. {
  177. break;
  178. }
  179. }
  180. frames++;
  181. /* call encoder */
  182. byte_counter = Encoder_Interface_Encode(enstate, req_mode, speech, serial_data, 0);
  183. if (frames % 64 == 0)
  184. rt_kprintf(".");
  185. bytes += byte_counter;
  186. fwrite(serial_data, sizeof(UWord8), byte_counter, file_encoded);
  187. fflush(file_encoded);
  188. }
  189. Encoder_Interface_exit(enstate);
  190. rt_kprintf("\n");
  191. #ifndef ETSI
  192. #ifdef IF2
  193. rt_kprintf("%s%i%s%i%s\n", "Frame structure AMR IF2: ", frames, " frames, ", bytes, " bytes.");
  194. #else
  195. rt_kprintf("%s%i%s%i%s\n", "Frame structure AMR MIME file storage format: ", frames, " frames, ", bytes,
  196. " bytes.");
  197. #endif
  198. #else
  199. rt_kprintf("%s%i%s\n", "Frame structure AMR ETSI: ", frames, " frames. ");
  200. #endif
  201. fclose(file_speech);
  202. fclose(file_encoded);
  203. if (file_mode != NULL)
  204. fclose(file_mode);
  205. rt_kprintf("encoder used %d.%03d s\n", (rt_tick_get_millisecond() - tick) / 1000, (rt_tick_get_millisecond() - tick) % 1000);
  206. }
  207. static void encoder(int argc, char *argv[])
  208. {
  209. if (argc != 5)
  210. {
  211. EncoderUsage();
  212. return;
  213. }
  214. // set file_mode_path
  215. memset(file_mode_path, 0, MODE_MAX_LEN);
  216. memcpy(file_mode_path, argv[2], strlen(argv[2]));
  217. // set file_speech_path
  218. memset(file_speech_path, 0, PATH_STRING_MAX_LEN);
  219. memcpy(file_speech_path, argv[3], strlen(argv[3]));
  220. // set file_encoded_path
  221. memset(file_encoded_path, 0, PATH_STRING_MAX_LEN);
  222. memcpy(file_encoded_path, argv[4], strlen(argv[4]));
  223. // create thread
  224. rt_thread_t thread = rt_thread_create("encoder", encoder_thread, RT_NULL, 24 * 1024, 21, 10);
  225. if (thread != RT_NULL)
  226. rt_thread_startup(thread);
  227. return;
  228. }
  229. #ifdef AMRNB_USING_CMD
  230. MSH_CMD_EXPORT_ALIAS(encoder, amr_encoder, AMR - NB encoder cmd);
  231. #endif