You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
7.4 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. #include "spisound.h"
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <getopt.h>
  5. #include <linux/spi/spidev.h>
  6. #include <linux/types.h>
  7. #include <pthread.h>
  8. #include <stdbool.h>
  9. #include <stdint.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h> //for strerror()
  13. #include <sys/ioctl.h>
  14. #include <unistd.h>
  15. #define MAX_ONE_FRAME_VOICE_SIZE 2000
  16. #define IOCTL(vfd, vkey, vvalue, errorcode) \
  17. { \
  18. int ret = ioctl(vfd, vkey, &vvalue); \
  19. if (ret != 0) { \
  20. close(vfd); \
  21. vfd = -1; \
  22. m_sys_error = errno; \
  23. m_last_error = errorcode; \
  24. return errorcode; \
  25. } \
  26. }
  27. // static const char *m_deviceName = NULL;
  28. static spisound_cb_t m_callback = NULL;
  29. static int m_fd = 0;
  30. static int m_sys_error = 0;
  31. static error_code_t m_last_error = ksp_success;
  32. static int m_cs_gpio_id = 0;
  33. static int m_gpiofd = 0;
  34. static pthread_t sound_read_thread;
  35. static bool inited = false;
  36. static bool started = false;
  37. static void *sound_read_thread_func(void *v);
  38. static void gpio_set_value(int value) { write(m_gpiofd, value ? "1\n" : "0\n", 2); }
  39. static void readvoice();
  40. typedef struct {
  41. int32_t *voice;
  42. int32_t size;
  43. } audio_t;
  44. static audio_t multiplierX2(int32_t *voice, int32_t size) {
  45. static int32_t voicebuf[MAX_ONE_FRAME_VOICE_SIZE * 2]; // 50ms
  46. for (size_t i = 0; i < size; i++) {
  47. voicebuf[i * 2] = voice[i];
  48. if (i + 1 < size) {
  49. voicebuf[i * 2 + 1] = (voice[i] + voice[i + 1]) / 2;
  50. } else {
  51. voicebuf[i * 2 + 1] = voice[i] + (voice[i] - voice[i - 1]);
  52. }
  53. }
  54. audio_t ret;
  55. ret.size = size * 2;
  56. ret.voice = voicebuf;
  57. return ret;
  58. }
  59. static audio_t multiplierX2_2(int32_t *voice, int32_t size) {
  60. static int32_t voicebuf[MAX_ONE_FRAME_VOICE_SIZE * 4]; // 50ms
  61. if (size > MAX_ONE_FRAME_VOICE_SIZE) {
  62. size = MAX_ONE_FRAME_VOICE_SIZE;
  63. }
  64. for (size_t i = 0; i < size; i++) {
  65. voicebuf[i * 2] = voice[i];
  66. if (i + 1 < size) {
  67. voicebuf[i * 2 + 1] = (voice[i] + voice[i + 1]) / 2;
  68. } else {
  69. voicebuf[i * 2 + 1] = voice[i] + (voice[i] - voice[i - 1]);
  70. }
  71. }
  72. audio_t ret;
  73. ret.size = size * 2;
  74. ret.voice = voicebuf;
  75. return ret;
  76. }
  77. static int32_t filter(int32_t input, int32_t v1, int32_t v2, int32_t v3, int32_t v4, int32_t v5, int32_t v6) {
  78. int32_t v[6];
  79. v[0] = v1;
  80. v[1] = v2;
  81. v[2] = v3;
  82. v[3] = v4;
  83. v[4] = v5;
  84. v[5] = v6;
  85. // 对v进行排序
  86. for (size_t i = 0; i < 6; i++) {
  87. for (size_t j = i + 1; j < 6; j++) {
  88. if (v[i] > v[j]) {
  89. int32_t tmp = v[i];
  90. v[i] = v[j];
  91. v[j] = tmp;
  92. }
  93. }
  94. }
  95. int expect = (v[2] + v[3]) / 2;
  96. if (abs(input) > abs(expect * 2) || abs(input) < abs(expect / 2)) {
  97. return expect;
  98. } else {
  99. return input;
  100. }
  101. }
  102. static bool filterVoice(int32_t *voice, int32_t size) {
  103. #if 1
  104. static int32_t vbuf[MAX_ONE_FRAME_VOICE_SIZE * 3]; // 50ms
  105. static int32_t vbufnum = 0;
  106. vbufnum++;
  107. memmove(vbuf, vbuf + size, 2 * size * sizeof(int32_t));
  108. memcpy(vbuf + 2 * size, voice, size * sizeof(int32_t));
  109. // printf("size:%d\n", size);
  110. if (vbufnum < 3) {
  111. return false;
  112. }
  113. int32_t *cachebegin = &vbuf[size];
  114. for (int i = 0; i < size; i++) {
  115. voice[i] = filter(*(cachebegin + i), //
  116. *(cachebegin + i - 1), //
  117. *(cachebegin + i - 2), //
  118. *(cachebegin + i - 3), //
  119. *(cachebegin + i + 1), //
  120. *(cachebegin + i + 2), //
  121. *(cachebegin + i + 3));
  122. // voice[i] = *(cachebegin + i);
  123. }
  124. return true;
  125. #endif
  126. #if 0
  127. static int32_t vbuf[MAX_ONE_FRAME_VOICE_SIZE]; // 50ms
  128. memcpy(vbuf, voice, size * sizeof(int32_t));
  129. int32_t *cachebegin = vbuf;
  130. for (int32_t i = 3; i < size - 3; i++) {
  131. voice[i] = filter(voice[i], *(cachebegin + i - 1), *(cachebegin + i - 2), *(cachebegin + i - 3), *(cachebegin + i + 1), *(cachebegin + i + 2),
  132. *(cachebegin + i + 3));
  133. // voice[i] = cachebegin[i];
  134. }
  135. #endif
  136. return true;
  137. }
  138. error_code_t spisound_init(const char *deviceName, int csgpionameId, spisound_cb_t callback) {
  139. m_callback = callback;
  140. m_cs_gpio_id = csgpionameId;
  141. //
  142. m_fd = open(deviceName, O_RDWR);
  143. if (m_fd < 0) {
  144. m_sys_error = errno;
  145. m_last_error = ksp_init_spi_error_open_fail;
  146. return ksp_init_spi_error_open_fail;
  147. }
  148. // 设置模式
  149. int mode = SPI_MODE_3;
  150. int bits = 8;
  151. int speed = 3000000;
  152. // SPI初始化
  153. IOCTL(m_fd, SPI_IOC_WR_MODE, mode, ksp_init_spi_error_set_mode_fail);
  154. IOCTL(m_fd, SPI_IOC_WR_BITS_PER_WORD, bits, ksp_init_spi_error_set_mode_fail);
  155. IOCTL(m_fd, SPI_IOC_WR_MAX_SPEED_HZ, speed, ksp_init_spi_error_set_mode_fail);
  156. char cmd[256] = {0};
  157. sprintf(cmd, "echo %d 1> /sys/class/gpio/export 2>/dev/null", m_cs_gpio_id);
  158. system(cmd);
  159. sprintf(cmd, "echo out > /sys/class/gpio/gpio%d/direction", m_cs_gpio_id);
  160. system(cmd);
  161. sprintf(cmd, "/sys/class/gpio/gpio%d/value", m_cs_gpio_id);
  162. m_gpiofd = open(cmd, O_RDWR);
  163. if (m_gpiofd < 0) {
  164. m_sys_error = errno;
  165. m_last_error = ksp_init_spi_cs_pin_open_fail;
  166. return ksp_init_spi_cs_pin_open_fail;
  167. }
  168. inited = true;
  169. return ksp_success;
  170. }
  171. static void *sound_read_thread_func(void *v) {
  172. while (true) {
  173. // 一次系统调用时间大概500us
  174. readvoice();
  175. usleep(10000);
  176. }
  177. return NULL;
  178. }
  179. error_code_t spisound_start_capture(void) {
  180. //
  181. if (!inited) {
  182. return ksp_module_not_inited;
  183. }
  184. if (started) {
  185. return ksp_module_has_started;
  186. }
  187. int ret = pthread_create(&sound_read_thread, NULL, sound_read_thread_func, NULL);
  188. if (ret != 0) {
  189. m_sys_error = errno;
  190. return ksp_create_thread_fail;
  191. }
  192. started = true;
  193. return ksp_success;
  194. }
  195. static void readvoice() {
  196. static int32_t voicebuf[MAX_ONE_FRAME_VOICE_SIZE]; // 50ms
  197. static int32_t rxdatabytesize; //
  198. rxdatabytesize = 0;
  199. memset(voicebuf, 0, sizeof(voicebuf));
  200. gpio_set_value(0);
  201. // usleep(1500); // CS信号触发后,给单片机足够的时间准备音频数据
  202. int ret = read(m_fd, &rxdatabytesize, 4);
  203. // printf("%d\n",rxdatabytesize);
  204. // printf("read rxdatabytesize:%d\n", rxdatabytesize);
  205. if (rxdatabytesize <= 0) {
  206. gpio_set_value(1);
  207. return;
  208. }
  209. if (rxdatabytesize > MAX_ONE_FRAME_VOICE_SIZE * 4) {
  210. printf("WARNING: rxdatabytesize(%d) > voiceBufSize \n", rxdatabytesize);
  211. gpio_set_value(1);
  212. return;
  213. }
  214. ret = read(m_fd, voicebuf, rxdatabytesize);
  215. gpio_set_value(1);
  216. static int count = 0;
  217. count++;
  218. if (count < 10) {
  219. return;
  220. }
  221. int32_t voiceframesize = 0;
  222. bool ready = filterVoice(voicebuf, rxdatabytesize / 4);
  223. if (ready) {
  224. audio_t v1 = multiplierX2(voicebuf, rxdatabytesize / 4);
  225. audio_t v2 = multiplierX2_2(v1.voice, v1.size);
  226. if (m_callback) m_callback(v2.voice, v2.size);
  227. // if (m_callback) m_callback(voicebuf, rxdatabytesize / 4);
  228. }
  229. return;
  230. }
  231. void spisound_dump_last_error() {
  232. printf("----------------spisound_dump_last_error-----------------\n");
  233. printf("- module error: %s(%d)\n", error_code_to_string(m_last_error), m_last_error);
  234. printf("- sys_ error : %s(%d)\n", strerror(m_sys_error), m_sys_error);
  235. printf("-\n");
  236. }
  237. const char *spisound_libversion() { return "1.0.0"; }