• linux网络编程(udp)传输音频


            udp传输音频,涉及对于网络编程,音频的处理,笔者这里做一点笔记。基于OSS的音频编程需要对于/dev/dsp操作,当然,如果你使用音频sdk包的话,就需要稍微进行修改。

            传输时声音的质量还可以。有时运行程序需要过一会才能听到声音。

            涉及了一些api的使用,如果使用不妥,会消耗很多时间,笔者也是踩了不少坑。

    服务端代码(收音并播放):

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. #include
    17. //#include "mi_common_datatype.h"
    18. //#include "mi_sys.h"
    19. //#include "mi_ai.h"
    20. //#include "mi_ao.h"
    21. //录音频率
    22. #define RATE 48000
    23. //量化位数
    24. #define SIZE 16
    25. //声道数目
    26. #define CHANNELS 2
    27. //缓冲区大小
    28. #define RSIZE 2048
    29. //保存录取的音频数据
    30. unsigned char buf[RSIZE];
    31. int main(int argc,char *argv[])
    32. {
    33. //声卡描述符
    34. int fd;
    35. int arg;
    36. int status;
    37. //socket
    38. struct sockaddr_in s_addr;
    39. struct sockaddr_in c_addr;
    40. int sock;
    41. socklen_t addr_len;
    42. int len;
    43. if((sock=socket(AF_INET,SOCK_DGRAM,0))==-1) //使用UDP方式
    44. {
    45. perror("socket");
    46. exit(errno);
    47. }
    48. else
    49. printf("creat socket success.\n\r");
    50. memset(&s_addr,0,sizeof(struct sockaddr_in));
    51. s_addr.sin_family=AF_INET; //协议设为AF_INET
    52. s_addr.sin_port=htons(8888); //接受端口为8888
    53. s_addr.sin_addr.s_addr=INADDR_ANY; //本地任意IP
    54. if((bind(sock,(struct sockaddr *) &s_addr,sizeof(s_addr)))==-1)
    55. {
    56. perror("bind error:");
    57. exit(errno);
    58. }
    59. else
    60. printf("bind address to socket.\n\r");
    61. addr_len=sizeof(c_addr);
    62. //声卡正常使用就用这个
    63. fd = open("/dev/dsp",O_WRONLY);
    64. if(fd < 0)
    65. {
    66. perror("Connot open /dev/dsp device");
    67. return 1;
    68. }
    69. //设置采样的量化位数
    70. arg = SIZE;
    71. status = ioctl(fd,SOUND_PCM_WRITE_BITS,&arg);
    72. if(status == -1)
    73. {
    74. perror("Connet set SOUND_PCM_WRITE_BITS ");
    75. return -1;
    76. }
    77. //设置采样时的声道数目
    78. arg = CHANNELS;
    79. status = ioctl(fd,SOUND_PCM_WRITE_CHANNELS,&arg);
    80. if(status == -1)
    81. {
    82. perror("Connet set SOUND_PCM_WRITE_CHANNELS ");
    83. return -1;
    84. }
    85. //设置采样时的频率
    86. arg = RATE;
    87. status = ioctl(fd,SOUND_PCM_WRITE_RATE,&arg);
    88. if(status == -1)
    89. {
    90. perror("Connet set SOUND_PCM_WRITE_RATE ");
    91. return -1;
    92. }
    93. #endif
    94. //一直接受播放,直到按下ctrl+c为止
    95. while(1)
    96. {
    97. len=recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr *)&c_addr,&addr_len);
    98. if(len<0)
    99. perror("receive error:");
    100. //播音
    101. write(fd,buf,RSIZE);
    102. memset(buf, 0, RSIZE);
    103. }
    104. //close(fd);
    105. close(sock);
    106. return 0;
    107. }

    客户端代码(录音并传输

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #include
    8. #include
    9. #include
    10. #include
    11. #include
    12. #include
    13. #include
    14. #include
    15. #include
    16. #include
    17. //录音频率
    18. #define RATE 48000
    19. //量化位数
    20. #define SIZE 16
    21. //声道数目
    22. #define CHANNELS 2
    23. //缓冲区大小
    24. #define RSIZE 1024
    25. //保存录取的音频数据
    26. unsigned char buf[RSIZE];
    27. int main(int argc,char *argv[])
    28. {
    29. int fd,sockfd;
    30. int status;
    31. int arg;
    32. struct sockaddr_in s_addr;
    33. if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
    34. {
    35. perror("socket");
    36. exit(errno);
    37. }
    38. else
    39. printf("creat sockfd success!.\n\r");
    40. // bzero(&s_addr,sizeof(struct sockaddr_in));
    41. s_addr.sin_family=AF_INET;
    42. s_addr.sin_port=htons(8888);
    43. if(argc!=2)
    44. {
    45. printf("用法:./udp-dsp-client IP地址。\n");
    46. return 1;
    47. }
    48. else
    49. s_addr.sin_addr.s_addr=inet_addr(argv[1]);
    50. bzero (&(s_addr.sin_zero),8);
    51. /*************读方式打开音频设备*******************************/
    52. fd= open("/dev/dsp",O_RDONLY,0777);
    53. if(fd < 0)
    54. {
    55. perror("Cannot open /dev/dsp device");
    56. return 1;
    57. }
    58. //设置采样的量化位数
    59. arg = SIZE;
    60. status = ioctl(fd,SOUND_PCM_WRITE_BITS,&arg);
    61. if(status == -1)
    62. {
    63. perror("Connet set SOUND_PCM_WRITE_BITS ");
    64. return -1;
    65. }
    66. //设置采样时的声道数目
    67. arg = CHANNELS;
    68. status = ioctl(fd,SOUND_PCM_WRITE_CHANNELS,&arg);
    69. if(status == -1)
    70. {
    71. perror("Connet set SOUND_PCM_WRITE_CHANNELS ");
    72. return -1;
    73. }
    74. //设置采样时的频率
    75. arg = RATE;
    76. status = ioctl(fd,SOUND_PCM_WRITE_RATE,&arg);
    77. if(status == -1)
    78. {
    79. perror("Connet set SOUND_PCM_WRITE_RATE ");
    80. return -1;
    81. }
    82. int readNum,sendNum;
    83. while(1)
    84. {
    85. //从声卡读语音数据
    86. readNum = read(fd,buf,RSIZE);
    87. if(readNum==-1)
    88. {
    89. perror("read wrong number of bytes\n");
    90. }
    91. //发送语音数据
    92. sendNum=sendto(sockfd,buf,readNum,0,(struct sockaddr * )&s_addr,sizeof(struct sockaddr));
    93. if(sendNum==-1){
    94. perror("send error:");
    95. exit(-1);
    96. }
    97. }
    98. close(fd);
    99. close(sockfd);
    100. return 0;
    101. }

          

  • 相关阅读:
    卷积神经网络实践-猫狗分类
    第七章 API及系统架构介绍
    EtcdServer初始化
    portainer + portainer/agent
    Flink监控和调优笔记
    Linux Shell脚本练习(一)
    Stable Diffusion之novel Ai教程,小白必经之路
    Java 和 JavaScript 有什么区别?
    关于前端开发中导入导出
    win10录音机入门指南,让你的录音更轻松
  • 原文地址:https://blog.csdn.net/weixin_44575952/article/details/126031005