[关闭]
@expl0r3r 2018-05-23T05:49:14.000000Z 字数 4305 阅读 328

Realtime.c

语音对讲


  1. #include <alsa/asoundlib.h> //alsa lib
  2. #include <unistd.h> //system call
  3. #include <pthread.h> //thread
  4. #include <semaphore.h> //signal
  5. #include <wiringPi.h> //raspberry pi GPIO
  6. #define RATE 22333
  7. #define CHANNEL 2
  8. #define FRAMES 128
  9. #define SIZE CHANNEL*FRAMES*1
  10. #define NBUFF 4
  11. long counter = 0;
  12. long second = 2;
  13. struct {
  14. char buffer[1024];
  15. sem_t nempty, nstored;
  16. char flag;
  17. } shared;
  18. char* pRead = shared.buffer;
  19. char* pWrite = shared.buffer;
  20. void* captureData(void *arg);
  21. void* playbackData(void *arg);
  22. void* press(void *arg);
  23. int main()
  24. {
  25. pthread_t tid_captureData, tid_playbackData, tid_press;
  26. //Initial
  27. sem_init(&shared.nempty, 0, NBUFF);
  28. sem_init(&shared.nstored, 0, 0);
  29. shared.flag = 1;//speaking mode
  30. //initiate GPIO to make speaker working at receiving mode
  31. wiringPiSetup();
  32. //GPIO initial, output mode, speaking mode
  33. pinMode(0, OUTPUT);
  34. digitalWrite(0, LOW);
  35. //create thread, capture data and save to buffer
  36. pthread_create(&tid_captureData, NULL, captureData, NULL);
  37. //create thread, get data from buffer and playback
  38. pthread_create(&tid_playbackData, NULL, playbackData, NULL);
  39. //create thread, press <enter> to change mode
  40. pthread_create(&tid_press, NULL, press, NULL);
  41. //for recycling resources
  42. pthread_join(tid_playbackData, NULL);
  43. pthread_join(tid_captureData, NULL);
  44. pthread_join(tid_press, NULL);
  45. //signal destruction
  46. sem_destroy(&shared.nempty);
  47. sem_destroy(&shared.nstored);
  48. exit(0);
  49. }
  50. //press <enter> to change mode
  51. void* press(void *arg)
  52. {
  53. while(1)
  54. {
  55. if(getchar() == '\n')
  56. {
  57. fflush(stdin);
  58. if(shared.flag == 0)
  59. {
  60. shared.flag = 1;
  61. usleep(1000);
  62. pinMode(0, OUTPUT);
  63. digitalWrite(0, LOW);
  64. printf("please speak");
  65. }
  66. else
  67. {
  68. shared.flag = 0;
  69. digitalWrite(0, HIGH);
  70. pinMode(0, INPUT);
  71. printf("please listen");
  72. }
  73. }
  74. }
  75. }
  76. void* captureData(void *arg)
  77. {
  78. int rc;
  79. snd_pcm_t *handle; //device handle
  80. snd_pcm_hw_params_t *params; //hardware info & config PCM stream
  81. unsigned int val = RATE;
  82. int dir;
  83. snd_pcm_uframes_t frames;
  84. rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);//open api, CALLBACK
  85. if(rc < 0)
  86. {
  87. printf("unable to open pcm device:%s\n", snd_strerror(rc));
  88. exit(1);
  89. }
  90. //setting hardware params
  91. snd_pcm_hw_params_alloca(&params); //alloca params struct
  92. snd_pcm_hw_params_any(handle, params); //initial params
  93. snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);//initial access permission
  94. snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8);//sampling bit
  95. snd_pcm_hw_params_set_channels(handle, params, 2); //channels
  96. snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //rate
  97. snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);//set period size
  98. rc = snd_pcm_hw_params(handle, params);
  99. if(rc < 0)
  100. {
  101. printf("unable to set hw parameters:%s\n", snd_strerror(rc));
  102. exit(1);
  103. }
  104. snd_pcm_hw_params_get_period_size(params, &frames, &dir);
  105. snd_pcm_hw_params_get_period_time(params, &val, &dir);
  106. while(1)
  107. {
  108. frames = FRAMES;
  109. sem_wait(&shared.nempty);//wait empty signal
  110. rc = snd_pcm_readi(handle, pWrite, frames);
  111. if(rc !=(int)frames)
  112. {
  113. usleep(1000);
  114. snd_pcm_prepare(handle);
  115. sem_post(&shared.nempty);
  116. continue; //reread
  117. }
  118. pWrite += 256;
  119. if(pWrite - 1024 == shared.buffer)
  120. pWrite = shared.buffer;
  121. sem_post(&shared.nstored);
  122. }
  123. snd_pcm_drain(handle);
  124. snd_pcm_close(handle);
  125. }
  126. void* playbackData(void *arg)
  127. {
  128. int rc;
  129. snd_pcm_t *handle;
  130. snd_pcm_hw_params_t *params;
  131. unsigned int val = RATE;
  132. int dir;
  133. snd_pcm_uframes_t frames;
  134. rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0); //PLAYBACK
  135. if(rc < 0)
  136. {
  137. printf("unable to open pcm device:%s\n", snd_strerror(rc));
  138. exit(1);
  139. }
  140. snd_pcm_hw_params_alloca(&params);
  141. snd_pcm_hw_params_any(handle, params);
  142. snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
  143. snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8);
  144. snd_pcm_hw_params_set_channels(handle, params, 2);
  145. snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
  146. snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
  147. rc = snd_pcm_hw_params(handle, params);
  148. if(rc < 0)
  149. {
  150. printf("unable to set hw parameters:%s\n", snd_strerror(rc));
  151. exit(1);
  152. }
  153. snd_pcm_hw_params_get_period_size(params, &frames, &dir);
  154. snd_pcm_hw_params_get_period_time(params, &val, &dir);
  155. while(1)
  156. {
  157. frames = FRAMES;
  158. sem_wait(&shared.nstored);
  159. rc = snd_pcm_writei(handle, pRead, frames);
  160. if(rc !=(int)frames)
  161. {
  162. usleep(1000);
  163. snd_pcm_prepare(handle);
  164. sem_post(&shared.nstored);
  165. continue; //reread
  166. }
  167. pRead += 256;
  168. if(pRead - 1024 == shared.buffer)
  169. pRead = shared.buffer;
  170. sem_post(&shared.nempty);
  171. if(0 == ++counter % 175)
  172. second++, printf("%ld\n", second);
  173. if(0 == second % 50)//50 seconds, stop base station contraler
  174. digitalWrite(0, HIGH);
  175. if(0 == (second / 51) - (second % 51))//2 seconds delay
  176. digitalWrite(0, LOW);
  177. }
  178. snd_pcm_drain(handle);
  179. snd_pcm_close(handle);
  180. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注