Linux如何在RAM缓冲区中录制声音并以自定义延迟播放音频

Linux如何在RAM缓冲区中录制声音并以自定义延迟播放音频,第1张

概述我需要使用嵌入式 Linux系统将音频从收音机发送到辅助系统. 辅助系统需要建立一个需要几秒钟的通信信道. 因此,如果我不想失去音频的开头,我需要一种方法来录制声音并以自定义延迟播放(最多几秒). 应该可以启动arecord将音频记录在tmpfs文件系统的文件中,并且当传入通信时,启动aplay. 但在这种情况下,开始仍然会丢失,因为要记录的信号来得太晚了. Linux上是否有一个程序可以在RAM 我需要使用嵌入式 Linux系统将音频从收音机发送到辅助系统.

辅助系统需要建立一个需要几秒钟的通信信道.

因此,如果我不想失去音频的开头,我需要一种方法来录制声音并以自定义延迟播放(最多几秒).

应该可以启动arecord将音频记录在tmpfs文件系统的文件中,并且当传入通信时,启动aplay.
但在这种情况下,开始仍然会丢失,因为要记录的信号来得太晚了.

linux上是否有一个程序可以在RAM中的环形缓冲区中连续录制声音,并且能够根据需要自定义延迟播放?

如果没有,在嵌入式系统上编写这样一个程序的最佳库是什么? alsa还是其他什么?

解决方法 这是一个简单的C程序,它将在管道输入和输出之间保持循环缓冲区.在|中使用buffer_program |出.错误检查省略.坚固性不保证.给出了一般的想法.

测试脚本(但实际上,因为它的循环缓冲区需要管道中的数据,以便它只需要流中的任何块.或者只是使缓冲区大于数据):

cat some.wav | ./circular_buffer 100000 | (sleep 1 && aplay)

circular_buffer.c:

/** * This program simply maintains a circular buffer of a given size indefinitely. */#include <stdio.h>#include <stddef.h>#include <unistd.h>#include <stdlib.h>#include <stdbool.h> /* C99 only */#include <sys/select.h>#include <errno.h>#include <fcntl.h>int c_read(int fd,char * buf,unsigned int size,unsigned int * head_in,unsigned int * tail_in);int c_write(int fd,unsigned int * tail_in);bool empty_buf(unsigned int head,unsigned int tail);bool setblock(int fd,bool block);#define FD_SET_SET(set,fd,max) FD_SET(fd,&set); max = ((fd > max) ? fd : max);#define FD_SET_UNSET(set,max) FD_CLR(fd,&set); max = ((fd == max) ? max - 1  : max);  //not IDeal. do while ISFDSET...int main(int argc,char **argv){  char * buf;  unsigned int buf_size = 0;  unsigned int buf_head = 0;  unsigned int buf_tail = 0;  // Check args.  if(argc != 2) {    fprintf(stderr,"Usage: %s <buffer size in bytes>\n",__file__);    exit(EXIT_FAILURE);  }  sscanf(argv[1],"%d",&buf_size);  buf_size = ( buf_size < 2 ) ? 2 : buf_size;  // Note the usable buffer space is buf_size-1.  fprintf(stderr,"Allocating %d\n",buf_size);  buf = (char*)malloc(buf_size);  bool done_reading = false;  int maxfd = 0;  fd_set r_set,w_set,r_tempset,w_tempset;  setblock(STDIN_fileNO,false);  setblock(STDOUT_fileNO,false);  FD_ZERO(&r_set);  FD_ZERO(&w_set);  FD_ZERO(&r_tempset);  FD_ZERO(&w_tempset);  FD_SET_SET(r_tempset,STDIN_fileNO,maxfd);  FD_SET_SET(w_tempset,STDOUT_fileNO,maxfd);  r_set = r_tempset;  while(true) {    select((maxfd + 1),&r_set,&w_set,NulL,NulL);    if(FD_ISSET(STDIN_fileNO,&r_set)) {      int c = c_read(STDIN_fileNO,buf,buf_size,&buf_head,&buf_tail);      if(c == -1) { // EOF,disable select on the input.        fprintf(stderr,"No more bytes to read\n");        done_reading = true;        FD_ZERO(&r_set);      }    }    if(!done_reading) {      r_set = r_tempset;    }    if(FD_ISSET(STDOUT_fileNO,&w_set)) {      c_write(STDOUT_fileNO,&buf_tail);    }    if(!empty_buf(buf_head,buf_tail)) { // Enable select on write whenever there is bytes.      w_set = w_tempset;    }    else {      FD_ZERO(&w_set);      if(done_reading) { // Finish.        fprintf(stderr,"No more bytes to write\n");        break;      }    }  }  fflush(stderr);  return 0;}bool empty_buf(unsigned int head,unsigned int tail) {  return head == tail;}/** * Keep reading until we can read no more. Keep on pushing the tail forward as we overflow. * Expects fd to be non blocking. * @returns number of byte read,0 on non stopPing error,or -1 on error or EOF. */int c_read(int fd,unsigned int * tail_in) {  fprintf(stderr,"In c_read()\n");  unsigned int head = *head_in;  unsigned int tail = *tail_in;  bool more_bytes = true;  int n = 0;  int c = 0;  while(more_bytes) {    bool in_front = tail > head;    fprintf(stderr,"Read %d %d %d\n",size,head,tail);    n = read(fd,buf+head,size - head);    if(n == -1) {      more_bytes = false;      if(errno == EAGAIN || errno == EWOulDBLOCK || errno == EINTR) { // Not EOF but the read would block.        c = 0;      }      else {        c = -1;      }    }    else if(n == 0) { // EOF. No more bytes possible.      more_bytes = false;      c = -1;    }    else if(n != (size - head)) { // if not full read adjust pointers and break.      more_bytes = false;      c += n;      head = (head+n)%size;      if(in_front && (head >= tail || head == 0)) {        tail = (head+1)%size;      }    }    else {      c = 0;      head = 0;      tail = (tail == 0) ? 1 : tail;    }  }  *head_in = head;  *tail_in = tail;  return c;}/** * Try flush the buffer to fd. fd should be non blocking. */int c_write(int fd,"In c_write()\n");  unsigned int head = *head_in;  unsigned int tail = *tail_in;  int n = 0;  fprintf(stderr,"Write %d %d %d\n",tail);  if(tail < head) {    n = write(fd,buf+tail,head-tail);    tail += n;  }  else if(head < tail) {    n = write(fd,size-tail);    if(n == size-tail) {      n = write(fd,head);      tail = n;    }  }  *head_in = head;  *tail_in = tail;  return n;}bool setblock(int fd,bool block){  int flags;  flags = fcntl(fd,F_GETFL);  if (block)      flags &= ~O_NONBLOCK;  else      flags |= O_NONBLOCK;  fcntl(fd,F_SETFL,flags);  return true;}
总结

以上是内存溢出为你收集整理的Linux如何在RAM缓冲区中录制声音并以自定义延迟播放音频全部内容,希望文章能够帮你解决Linux如何在RAM缓冲区中录制声音并以自定义延迟播放音频所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/yw/1039867.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-24
下一篇 2022-05-24

发表评论

登录后才能评论

评论列表(0条)

保存