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.

178 lines
6.2 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. #include <errno.h>
  2. #include <fcntl.h>
  3. #include <getopt.h>
  4. #include <linux/spi/spidev.h>
  5. #include <linux/types.h>
  6. #include <stdbool.h>
  7. #include <stdint.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <sys/ioctl.h>
  12. #include <unistd.h>
  13. #include <fstream>
  14. #include <iostream>
  15. #include <list>
  16. #include <map>
  17. #include <memory>
  18. #include <set>
  19. #include <sstream>
  20. #include <string>
  21. #include <vector>
  22. extern "C" {
  23. #include "libiflytop_adc_capture.h"
  24. }
  25. using namespace std;
  26. class WAVHeader {
  27. public:
  28. /**
  29. * @brief WAV
  30. *
  31. * WAV
  32. * - "RIFF" 4 chunk_id
  33. * - - 8 4 chunk_size
  34. * - "WAVE" 4 format
  35. * - "fmt " 4 subchunk1_id
  36. * - 16 4 subchunk1_size
  37. * - 1 PCM 2 audio_format
  38. * - 1 2 2 num_channels
  39. * - 44100 4 sample_rate
  40. * - * * / 8 4 byte_rate
  41. * - 2 16 2 2 block_align
  42. * - 8162432 2 bits_per_sample
  43. * - "data" 4 subchunk2_id
  44. * - - 44 4 subchunk2_size
  45. */
  46. struct WAVHeaderBinary {
  47. char chunk_id[4]; // 固定为 "RIFF"
  48. uint32_t chunk_size; // 文件总大小 - 8
  49. char format[4]; // 固定为 "WAVE"
  50. char subchunk1_id[4]; // 固定为 "fmt "
  51. uint32_t subchunk1_size; // 固定为 16
  52. uint16_t audio_format; // 编码格式,1 表示 PCM 编码
  53. uint16_t num_channels; // 声道数,1 为单声道,2 为立体声
  54. uint32_t sample_rate; // 采样率,如 44100
  55. uint32_t byte_rate; // 数据传输速率,即采样率 * 声道数 * 位数 / 8
  56. uint16_t block_align; // 数据块对齐,即每个采样点占用的字节数,如 2 表示 16 位,即 2 字节
  57. uint16_t bits_per_sample; // 位数,如 8、16、24、32
  58. char subchunk2_id[4]; // 固定为 "data"
  59. uint32_t subchunk2_size; // 数据长度,即文件总大小 - 44
  60. };
  61. WAVHeaderBinary header;
  62. public:
  63. WAVHeader() {}
  64. void initialize(uint32_t sample_rate, uint16_t bits_per_sample, uint16_t num_channels, uint32_t wavbinsize) {
  65. // 填充 RIFF 头
  66. memcpy(header.chunk_id, "RIFF", 4);
  67. header.chunk_size = wavbinsize + 44 - 8;
  68. memcpy(header.format, "WAVE", 4);
  69. // 填充 fmt 子块
  70. memcpy(header.subchunk1_id, "fmt ", 4);
  71. header.subchunk1_size = 16;
  72. header.audio_format = 1; // PCM 编码
  73. header.num_channels = num_channels;
  74. header.sample_rate = sample_rate;
  75. header.byte_rate = sample_rate * num_channels * bits_per_sample / 8;
  76. header.block_align = num_channels * bits_per_sample / 8;
  77. header.bits_per_sample = bits_per_sample;
  78. // 填充 data 子块
  79. memcpy(header.subchunk2_id, "data", 4);
  80. header.subchunk2_size = wavbinsize;
  81. }
  82. void resize(uint32_t wavbinsize) {
  83. header.chunk_size = wavbinsize + 44 - 8;
  84. header.subchunk2_size = wavbinsize;
  85. }
  86. void dump() {
  87. printf("chunk_id: %s\n", string(header.chunk_id, 4).c_str());
  88. printf("chunk_size: %d\n", header.chunk_size);
  89. printf("format: %s\n", string(header.format, 4).c_str());
  90. printf("subchunk1_id: %s\n", string(header.subchunk1_id, 4).c_str());
  91. printf("subchunk1_size: %d\n", header.subchunk1_size);
  92. printf("audio_format: %d\n", header.audio_format);
  93. printf("num_channels: %d\n", header.num_channels);
  94. printf("sample_rate: %d\n", header.sample_rate);
  95. printf("byte_rate: %d\n", header.byte_rate);
  96. printf("block_align: %d\n", header.block_align);
  97. printf("bits_per_sample: %d\n", header.bits_per_sample);
  98. printf("subchunk2_id: %s\n", header.subchunk2_id);
  99. printf("subchunk2_size: %d\n", header.subchunk2_size);
  100. }
  101. WAVHeader(uint32_t sample_rate, uint16_t bits_per_sample, uint16_t num_channels, uint32_t num_samples) {
  102. initialize(sample_rate, bits_per_sample, num_channels, num_samples);
  103. }
  104. uint8_t* data() { return (uint8_t*)&header; }
  105. size_t size() { return sizeof(header); }
  106. };
  107. void wavWriteVoice(string filename, uint32_t sample_rate, uint16_t bits_per_sample, uint16_t num_channels, const char* data, uint32_t size) {
  108. fstream file;
  109. WAVHeader wavHeader;
  110. // logger->info("writeVoice filename:{} {} {} {} {}", filename, sample_rate, bits_per_sample, num_channels, size);
  111. file.open(filename, fstream::in | fstream::out | fstream::binary);
  112. if (!file.is_open()) {
  113. file.open(filename, fstream::out | fstream::binary | fstream::trunc);
  114. wavHeader.initialize(sample_rate, bits_per_sample, num_channels, 0);
  115. file.seekp(0, ios::beg);
  116. file.write((char*)wavHeader.data(), wavHeader.size());
  117. file.close();
  118. file.open(filename, fstream::in | fstream::out | fstream::binary);
  119. }
  120. // file.write(data, size);
  121. #if 1
  122. /**
  123. * @brief 44
  124. */
  125. file.seekp(0, ios::end);
  126. file.write(data, size);
  127. /**
  128. * @brief
  129. */
  130. uint32_t filesize = file.tellp();
  131. file.seekp(4, ios::beg);
  132. uint32_t chunk_size = filesize - 8;
  133. file.write((char*)&chunk_size, 4);
  134. file.seekp(40, ios::beg);
  135. uint32_t subchunk2_size = filesize - 44;
  136. file.write((char*)&subchunk2_size, 4);
  137. #endif
  138. file.close();
  139. }
  140. void sound_capture_callback(int32_t* voicedata, uint32_t len) {
  141. printf("sound_capture_callback:%d\n", len);
  142. wavWriteVoice("record.wav", 48000, 32, 1, (char*)voicedata, len * sizeof(int32_t));
  143. }
  144. int main(int argc, char const* argv[]) {
  145. system("rm -rf record.wav");
  146. error_code_t erro_code = sound_capturer_init("/dev/spidev1.0", 59, sound_capture_callback);
  147. if (erro_code != ksp_success) {
  148. sound_capturer_dump_last_error();
  149. return -1;
  150. }
  151. erro_code = sound_capturer_start();
  152. if (erro_code != ksp_success) {
  153. sound_capturer_dump_last_error();
  154. return -1;
  155. }
  156. while (true) {
  157. sleep(1);
  158. }
  159. return 0;
  160. }