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.

253 lines
6.6 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
  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. if (size > MAX_ONE_FRAME_VOICE_SIZE) {
  47. size = MAX_ONE_FRAME_VOICE_SIZE;
  48. }
  49. for (size_t i = 0; i < size; i++) {
  50. voicebuf[i * 2] = voice[i];
  51. if (i + 1 < size) {
  52. voicebuf[i * 2 + 1] = (voice[i] + voice[i + 1]) / 2;
  53. }
  54. }
  55. audio_t ret;
  56. ret.size = size * 2;
  57. ret.voice = voicebuf;
  58. return ret;
  59. }
  60. static audio_t multiplierX2_2(int32_t *voice, int32_t size) {
  61. static int32_t voicebuf[MAX_ONE_FRAME_VOICE_SIZE * 4]; // 50ms
  62. if (size > MAX_ONE_FRAME_VOICE_SIZE) {
  63. size = MAX_ONE_FRAME_VOICE_SIZE;
  64. }
  65. for (size_t i = 0; i < size; i++) {
  66. voicebuf[i * 2] = voice[i];
  67. if (i + 1 < size) {
  68. voicebuf[i * 2 + 1] = (voice[i] + voice[i + 1]) / 2;
  69. }
  70. }
  71. audio_t ret;
  72. ret.size = size * 2;
  73. ret.voice = voicebuf;
  74. return ret;
  75. }
  76. 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) {
  77. int32_t v[6];
  78. v[0] = v1;
  79. v[1] = v2;
  80. v[2] = v3;
  81. v[3] = v4;
  82. v[4] = v5;
  83. v[5] = v6;
  84. // 对v进行排序
  85. for (size_t i = 0; i < 6; i++) {
  86. for (size_t j = i + 1; j < 6; j++) {
  87. if (v[i] > v[j]) {
  88. int32_t tmp = v[i];
  89. v[i] = v[j];
  90. v[j] = tmp;
  91. }
  92. }
  93. }
  94. int expect = (v[2] + v[3]) / 2;
  95. if (abs(input) > abs(expect * 2) || abs(input) < abs(expect / 2)) {
  96. return expect;
  97. } else {
  98. return input;
  99. }
  100. }
  101. static bool filterVoice(int32_t *voice, int32_t size) {
  102. #if 0
  103. static int32_t vbuf[MAX_ONE_FRAME_VOICE_SIZE * 3]; // 50ms
  104. static int32_t vbufnum = 0;
  105. vbufnum++;
  106. memmove(vbuf, vbuf + size, 2 * size * sizeof(int32_t));
  107. memcpy(vbuf + 2 * size, voice, size * sizeof(int32_t));
  108. if (vbufnum < 3) {
  109. return false;
  110. }
  111. #endif
  112. static int32_t vbuf[MAX_ONE_FRAME_VOICE_SIZE]; // 50ms
  113. memcpy(vbuf, voice, size * sizeof(int32_t));
  114. int32_t *cachebegin = vbuf;
  115. for (int32_t i = 3; i < size - 3; i++) {
  116. voice[i] = filter(voice[i], *(cachebegin + i - 1), *(cachebegin + i - 2), *(cachebegin + i - 3), *(cachebegin + i + 1), *(cachebegin + i + 2),
  117. *(cachebegin + i + 3));
  118. // voice[i] = cachebegin[i];
  119. }
  120. return true;
  121. }
  122. error_code_t spisound_init(const char *deviceName, int csgpionameId, spisound_cb_t callback) {
  123. m_callback = callback;
  124. m_cs_gpio_id = csgpionameId;
  125. //
  126. m_fd = open(deviceName, O_RDWR);
  127. if (m_fd < 0) {
  128. m_sys_error = errno;
  129. m_last_error = ksp_init_spi_error_open_fail;
  130. return ksp_init_spi_error_open_fail;
  131. }
  132. // 设置模式
  133. int mode = SPI_MODE_3;
  134. int bits = 8;
  135. int speed = 3000000;
  136. // SPI初始化
  137. IOCTL(m_fd, SPI_IOC_WR_MODE, mode, ksp_init_spi_error_set_mode_fail);
  138. IOCTL(m_fd, SPI_IOC_WR_BITS_PER_WORD, bits, ksp_init_spi_error_set_mode_fail);
  139. IOCTL(m_fd, SPI_IOC_WR_MAX_SPEED_HZ, speed, ksp_init_spi_error_set_mode_fail);
  140. char cmd[256] = {0};
  141. sprintf(cmd, "echo %d 1> /sys/class/gpio/export 2>/dev/null", m_cs_gpio_id);
  142. system(cmd);
  143. sprintf(cmd, "echo out > /sys/class/gpio/gpio%d/direction", m_cs_gpio_id);
  144. system(cmd);
  145. sprintf(cmd, "/sys/class/gpio/gpio%d/value", m_cs_gpio_id);
  146. m_gpiofd = open(cmd, O_RDWR);
  147. if (m_gpiofd < 0) {
  148. m_sys_error = errno;
  149. m_last_error = ksp_init_spi_cs_pin_open_fail;
  150. return ksp_init_spi_cs_pin_open_fail;
  151. }
  152. inited = true;
  153. return ksp_success;
  154. }
  155. static void *sound_read_thread_func(void *v) {
  156. while (true) {
  157. // 一次系统调用时间大概500us
  158. readvoice();
  159. usleep(10000);
  160. }
  161. return NULL;
  162. }
  163. error_code_t spisound_start_capture(void) {
  164. //
  165. if (!inited) {
  166. return ksp_module_not_inited;
  167. }
  168. if (started) {
  169. return ksp_module_has_started;
  170. }
  171. int ret = pthread_create(&sound_read_thread, NULL, sound_read_thread_func, NULL);
  172. if (ret != 0) {
  173. m_sys_error = errno;
  174. return ksp_create_thread_fail;
  175. }
  176. started = true;
  177. return ksp_success;
  178. }
  179. static void readvoice() {
  180. static int32_t voicebuf[MAX_ONE_FRAME_VOICE_SIZE]; // 50ms
  181. static int32_t rxdatabytesize; //
  182. rxdatabytesize = 0;
  183. memset(voicebuf, 0, sizeof(voicebuf));
  184. gpio_set_value(0);
  185. // usleep(1500); // CS信号触发后,给单片机足够的时间准备音频数据
  186. int ret = read(m_fd, &rxdatabytesize, 4);
  187. // printf("%d\n",rxdatabytesize);
  188. // printf("read rxdatabytesize:%d\n", rxdatabytesize);
  189. if (rxdatabytesize <= 0) {
  190. gpio_set_value(1);
  191. return;
  192. }
  193. if (rxdatabytesize > MAX_ONE_FRAME_VOICE_SIZE * 4) {
  194. printf("WARNING: rxdatabytesize(%d) > voiceBufSize \n", rxdatabytesize);
  195. gpio_set_value(1);
  196. return;
  197. }
  198. ret = read(m_fd, voicebuf, rxdatabytesize);
  199. gpio_set_value(1);
  200. int32_t voiceframesize = 0;
  201. bool ready = filterVoice(voicebuf, rxdatabytesize / 4);
  202. if (ready) {
  203. audio_t v1 = multiplierX2(voicebuf, rxdatabytesize / 4);
  204. audio_t v2 = multiplierX2_2(v1.voice, v1.size);
  205. if (m_callback) m_callback(v2.voice, v2.size);
  206. }
  207. return;
  208. }
  209. void spisound_dump_last_error() {
  210. printf("----------------spisound_dump_last_error-----------------\n");
  211. printf("- module error: %s(%d)\n", error_code_to_string(m_last_error), m_last_error);
  212. printf("- sys_ error : %s(%d)\n", strerror(m_sys_error), m_sys_error);
  213. printf("-\n");
  214. }
  215. const char *spisound_libversion() { return "1.0.0"; }