Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ can';t在ALSA raspberry pi c应用程序上配置硬件参数_C++_Raspberry Pi_Alsa_Libalsa - Fatal编程技术网

C++ can';t在ALSA raspberry pi c应用程序上配置硬件参数

C++ can';t在ALSA raspberry pi c应用程序上配置硬件参数,c++,raspberry-pi,alsa,libalsa,C++,Raspberry Pi,Alsa,Libalsa,我试图编写一个用于录制音频的ALSA应用程序,当我试图设置一些参数,然后将它们打印到屏幕上时,我会得到一些无法更改的默认数字 #include <alsa/asoundlib.h> using namespace std; typedef struct { int audio; int recording; void *cons; snd_pcm_t *inhandle; snd_pcm_t *outhandle; unsigned long sam

我试图编写一个用于录制音频的ALSA应用程序,当我试图设置一些参数,然后将它们打印到屏幕上时,我会得到一些无法更改的默认数字

#include <alsa/asoundlib.h>

using namespace std;


typedef struct {  
  int audio;
  int recording;
  void *cons;
  snd_pcm_t *inhandle;
  snd_pcm_t *outhandle;
  unsigned long sampleIndex;
  unsigned long inlen;
  unsigned long sampleRate;
} audio_t;
static audio_t aud;


void aboutAlsa(snd_pcm_t *handle,snd_pcm_hw_params_t *params) {
  unsigned int val, val2;
  snd_pcm_format_t val3;
  int dir;
  snd_pcm_uframes_t frames;

  printf("ALSA library version: %s\n",SND_LIB_VERSION_STR);
  printf("PCM handle name = '%s'\n",snd_pcm_name(handle));
  printf("PCM state = %s\n",snd_pcm_state_name(snd_pcm_state(handle)));
  snd_pcm_hw_params_get_access(params,(snd_pcm_access_t *) &val);
  printf("access type = %s\n",snd_pcm_access_name((snd_pcm_access_t)val));
  snd_pcm_hw_params_get_format(params, &val3);
  printf("format = '%s' (%s)\n",snd_pcm_format_name(val3),
    snd_pcm_format_description(val3));
  snd_pcm_hw_params_get_subformat(params,(snd_pcm_subformat_t *)&val);
  printf("subformat = '%s' (%s)\n",snd_pcm_subformat_name((snd_pcm_subformat_t)val),
    snd_pcm_subformat_description((snd_pcm_subformat_t)val));
  snd_pcm_hw_params_get_channels(params, &val);
  printf("channels = %d\n", val);
  snd_pcm_hw_params_get_rate(params, &val, &dir);
  printf("rate = %d bps\n", val);
  snd_pcm_hw_params_get_period_time(params,&val, &dir);
  printf("period time = %d us\n", val);
  snd_pcm_hw_params_get_period_size(params,&frames, &dir);
  printf("period size = %d frames\n", (int)frames);
  snd_pcm_hw_params_get_buffer_time(params,&val, &dir);
  printf("buffer time = %d us\n", val);
  snd_pcm_hw_params_get_buffer_size(params,(snd_pcm_uframes_t *) &val);
  printf("buffer size = %d frames\n", val);
  snd_pcm_hw_params_get_periods(params, &val, &dir);
  printf("periods per buffer = %d frames\n", val);
  snd_pcm_hw_params_get_rate_numden(params,&val, &val2);
  printf("exact rate = %d/%d bps\n", val, val2);
  val = snd_pcm_hw_params_get_sbits(params);
  printf("significant bits = %d\n", val);
  return;
}

static int openKnownAudio(int record) {
  int rc;
  int SAMPLERATE = 16000;
  unsigned int val;
  int dir=0;
  snd_pcm_t *handle;
  snd_pcm_hw_params_t *hw_params=NULL;
  snd_pcm_uframes_t frames;
  size_t esz = 256;
  char err[esz];
  /* Open PCM device for recording (capture). */ 
  if (record) {
    if ((rc=snd_pcm_open(&aud.inhandle, "default",SND_PCM_STREAM_CAPTURE, 0))<0) {
      snprintf(err, esz, "unable to open pcm device for recording: %s\n",snd_strerror(rc));
    }
    handle=aud.inhandle;
  } else {
    if ((rc=snd_pcm_open(&aud.outhandle, "default",SND_PCM_STREAM_PLAYBACK, 0))<0) {
      snprintf(err, esz, "unable to open pcm device for playback: %s\n",snd_strerror(rc));
    }
    handle=aud.outhandle;
  }

  /* Configure hardware parameters  */
  if((rc=snd_pcm_hw_params_malloc(&hw_params)) < 0) {
    snprintf(err, esz, "unable to malloc hw_params: %s\n",snd_strerror(rc));
  }
  if((rc=snd_pcm_hw_params_any(handle, hw_params))<0) {
    snprintf(err, esz, "unable to setup hw_params: %s\n",snd_strerror(rc));
  }
  if((rc=snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED))<0) {
    snprintf(err, esz, "unable to set access mode: %s\n",snd_strerror(rc));
  }
  if((rc=snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE))<0) {
    snprintf(err, esz, "unable to set format: %s\n",snd_strerror(rc));
  }
  if((rc=snd_pcm_hw_params_set_channels(handle, hw_params, 1))<0) {
    snprintf(err, esz, "unable to set channels: %s\n",snd_strerror(rc));
  }
  val = SAMPLERATE;
  dir = 0;
  if((rc=snd_pcm_hw_params_set_rate(handle, hw_params, SAMPLERATE,0))<0) {
    snprintf(err, esz, "unable to set samplerate: %s\n",snd_strerror(rc));
  }
  if (val!=SAMPLERATE) {
    snprintf(err, esz, "unable to set requested samplerate: requested=%i got=%i\n",SAMPLERATE,val);
  }
  frames = 64; 
  if ((rc=snd_pcm_hw_params_set_period_size_near(handle,hw_params, &frames, &dir))<0) {
    snprintf(err, esz, "unable to set period size: %s\n",snd_strerror(rc));
  }
  frames = 4096; 
  if ((rc=snd_pcm_hw_params_set_buffer_size_near(handle,hw_params, &frames))<0) {
    snprintf(err, esz, "unable to set buffer size: %s\n",snd_strerror(rc));
  }

  if ((rc = snd_pcm_hw_params(handle, hw_params))<0) {
    snprintf(err, esz, "unable to set hw parameters: %s\n",snd_strerror(rc));
  }

  aboutAlsa(handle,hw_params);

  snd_pcm_hw_params_free(hw_params);
  aud.recording = (record)? 1:0;
  aud.audio=1;
  return 1;
}
这是我在台式电脑上运行它时得到的结果:

ALSA library version: 1.0.28
PCM handle name = 'default'
PCM state = PREPARED
access type = RW_INTERLEAVED
format = 'S16_LE' (Signed 16 bit Little Endian)
subformat = 'STD' (Standard)
channels = 1
rate = 16000 bps
period time = 4000 us
period size = 64 frames
buffer time = 256000 us
buffer size = 4096 frames
periods per buffer = 64 frames
exact rate = 16000/1 bps
significant bits = 16
正如您所见,我试图将时段大小设置为64并返回341,该值仅在我更改速率时更改,假设我将速率设置为44100,这就是我返回的值:

rate = 44100 bps
period time = 21333 us
period size = 940 frames
buffer time = 85328 us
buffer size = 3763 frames
periods per buffer = 3763 frames

在台式pc上,这种情况没有发生,我试图在alsa lib中跟踪此功能,但我在那里迷路了,也尝试了不同的声卡,仍然得到相同的结果。

如果是PulseAudio,您设置的是PulseAudio设备,而不是真正的设备。 真正的硬件可能有局限性,您必须正确应对。 如果要查看某个参数的最小/最大边界,可以执行以下操作:

  • 使用snd_pcm_hw_参数转储函数
  • snd_pcm_hw_params_t*params;
    snd_pcm_t*pcm_手柄;
    int-pcm;
    /*在播放模式下打开PCM设备*/
    pcm=snd_pcm_打开(&pcm_手柄,pcm_设备,snd_pcm_流播放,0);
    如果(pcm<0){
    printf(“错误:无法打开\%s\”PCM设备。%s\n”,PCM\u设备,snd\u strerror(PCM));
    转到错误处理;
    }
    /*分配参数对象并用默认值填充它*/
    snd_pcm_hw_params_alloca(¶ms);
    pcm=snd_pcm_hw_params_any(pcm_handle,params);
    如果(pcm<0){
    printf(“此PCM的配置中断:没有可用的配置\n”);
    转到错误处理;
    }
    printf(“硬件边界参数************************\n”);
    snd_pcm_硬件_参数_转储(参数,日志);
    printf(“************************************************************\n”);
    
  • 使用最小值/最大值函数也是一样的

    snd_pcm_t*pcm;
    snd_pcm_硬件参数*硬件参数;
    int参数;
    //... 在此处打开设备并分配硬件参数
    /*用PCM的完整配置空间填充参数。
    配置空间将充满所有可能的内容
    PCM设备的范围*/
    snd_pcm_hw_参数_any(pcm,hw_参数);
    /*请用实际参数名替换
    例如缓冲区大小、缓冲区时间、速率等*/
    snd_pcm_hw_params_get_min(hw_参数和参数);
    printf(“最小值:%d/n”,参数);
    snd_pcm_hw_params_get_max(hw_参数和参数);
    printf(“最大值:%d/n”,参数);
    
  • 当我试图设置周期大小时,我也面临同样的问题。 有我的边界(两个不同的pcm设备):

    日志#1

    日志#2


    由于时段时间限制,我们无法更改时段大小。

    您是否尝试过通过/proc文件增加prealloc?这是第二个回应。根据我的经验,这允许更大的缓冲区大小、周期等。Pi可能不使用
    dmix
    。在任何情况下,不同的硬件具有不同的功能。@CL。这不是硬件问题。我发现当安装pulseaudio时,它解决了问题,但又制造了另一个问题,我不想使用pulseaudio!pulseaudio附带了万亿个软件包,我认为其中一个解决了这个问题,甚至可能是pulseaudio自己。我想我会发现alsa lib中的结构snd_间隔对于各种配置(通道、采样位等)有最小值和最大值。周期大小的这个值将告诉周期大小可能的最小值和最大值(检查元素间隔中的SNDRV_PCM_HW_参数Period_大小索引)。。如果请求的时段大小值小于最小值,alsa lib将不设置该值。正如@CL告诉不同的硬件有不同的capabilities@Varun在哪里可以看到最小/最大值?只是为了确保我试着将周期大小设置为不同的值,从很小到很大,只是不改变值始终保持不变(341帧)
    rate = 44100 bps
    period time = 21333 us
    period size = 940 frames
    buffer time = 85328 us
    buffer size = 3763 frames
    periods per buffer = 3763 frames
    
    hw boundary params  ***********************
    ACCESS:  RW_INTERLEAVED
    FORMAT:  U8 S16_LE S16_BE S24_LE S24_BE S32_LE S32_BE FLOAT_LE FLOAT_BE MU_LAW A_LAW S24_3LE S24_3BE
    SUBFORMAT:  STD
    SAMPLE_BITS: [8 32]
    FRAME_BITS: [8 1024]
    CHANNELS: [1 32]
    RATE: [1 192000]
    PERIOD_TIME: (5 4294967295)
    PERIOD_SIZE: [1 1398102)
    PERIOD_BYTES: [128 1398102)
    PERIODS: [3 1024]
    BUFFER_TIME: (15 4294967295]
    BUFFER_SIZE: [3 4194304]
    BUFFER_BYTES: [384 4194304]
    TICK_TIME: ALL
    *******************************************
    
    **********************************DEBUG 
    period time min    : 21333
    period time max    : 21334
    buffer time min    : 1
    buffer time max    : -1
    channels min       : 1
    channels max       : 10000
    rate  min          : 4000
    rate  max          : -1
    period size min    : 85
    period size max    : 91628833
    buffer size min    : 170
    buffer size max    : 274877906
    **********************************DEBUG_END