簡體   English   中英

無法在 ALSA raspberry pic 應用程序上配置硬件參數

[英]can't configure hardware parameters on ALSA raspberry pi c appliction

我嘗試編寫 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;
}

這是我在 raspberry pi 上運行時得到的:

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 = 21333 us
period size = 341 frames
buffer time = 256000 us
buffer size = 4096 frames
periods per buffer = 4096 frames
exact rate = 16000/1 bps
significant bits = 16

這就是我在台式機上運行時得到的結果:

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

在台式電腦上,這不會發生我試圖在 alsa-lib 中追蹤這些功能,但我在那里迷路了也嘗試了不同的聲卡,但仍然得到相同的結果。

在 PulseAudio 的情況下,您確實設置了 PulseAudio device ,而不是真正的設備。 真正的硬件可能有局限性,您必須正確應對。 如果您想查看某個參數的最小/最大邊界,您可以執行以下操作:

  1. 使用 snd_pcm_hw_params_dump 函數
    snd_pcm_hw_params_t *params;
    snd_pcm_t *pcm_handle;
    int pcm;
    
    /* Open the PCM device in playback mode */
    pcm = snd_pcm_open(&pcm_handle, PCM_DEVICE, SND_PCM_STREAM_PLAYBACK, 0);
    if (pcm < 0) {
        printf("ERROR: Can't open \"%s\" PCM device. %s\n", PCM_DEVICE, snd_strerror(pcm));
        goto error_handling;
    }
    
    /* Allocate parameters object and fill it with default values*/
    snd_pcm_hw_params_alloca(&params);
    
    pcm = snd_pcm_hw_params_any(pcm_handle, params);
    if (pcm < 0) {
        printf("Broken configuration for this PCM: no configurations available\n");
        goto error_handling;
    }
    
    printf("hw boundary params  ***********************\n");
    snd_pcm_hw_params_dump(params, log);
    printf("*******************************************\n");
  1. 同樣使用最小/最大函數

    snd_pcm_t* pcm; snd_pcm_hw_params_t* hw_parameters; int parameter; //... open device and allocate hw params here /*Fill params with a full configuration space for a PCM. The configuration space will be filled with all possible ranges for the PCM device.*/ snd_pcm_hw_params_any(pcm,hw_parameters); /* please substitute <parameter name> with real parameter name for example buffer_size, buffer_time, rate, etc*/ snd_pcm_hw_params_get_<parameter name>_min(hw_parameters,&parameter); printf("<parameter name> min : %d/n", parameter); snd_pcm_hw_params_get_<parameter name>_max(hw_parameters,&parameter); printf("<parameter name> max : %d/n", parameter);

我在嘗試設置周期大小時遇到​​了同樣的問題。 有我的邊界(兩個不同的 pcm 設備):

日志 #1

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
*******************************************

日志#2

**********************************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

此處由於周期時間限制,我們無法更改周期大小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM