⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 speaker-test.c

📁 ALSA驱动的一些调试测试工具
💻 C
📖 第 1 页 / 共 2 页
字号:
    uint32_t length;    uint32_t type;  } hdr;  struct {    uint32_t type;    uint32_t length;  } chunk1;  struct {    uint16_t format;    uint16_t channels;    uint32_t rate;    uint32_t bytes_per_sec;    uint16_t sample_size;    uint16_t sample_bits;  } body;  struct {    uint32_t type;    uint32_t length;  } chunk;};#if __BYTE_ORDER == __LITTLE_ENDIAN#define COMPOSE_ID(a,b,c,d)	((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))#define LE_SHORT(v)		(v)#define LE_INT(v)		(v)#else#define COMPOSE_ID(a,b,c,d)	((d) | ((c)<<8) | ((b)<<16) | ((a)<<24))#define LE_SHORT(v)		bswap_16(v)#define LE_INT(v)		bswap_32(v)#endif#define WAV_RIFF		COMPOSE_ID('R','I','F','F')#define WAV_WAVE		COMPOSE_ID('W','A','V','E')#define WAV_FMT			COMPOSE_ID('f','m','t',' ')#define WAV_DATA		COMPOSE_ID('d','a','t','a')#define WAV_PCM_CODE		1static const char *search_for_file(const char *name){  char *file;  if (*name == '/')    return strdup(name);  file = malloc(strlen(wav_file_dir) + strlen(name) + 2);  if (file)    sprintf(file, "%s/%s", wav_file_dir, name);  return file;}static int check_wav_file(int channel, const char *name){  struct wave_header header;  int fd;  wav_file[channel] = search_for_file(name);  if (! wav_file[channel]) {    fprintf(stderr, _("No enough memory\n"));    return -ENOMEM;  }  if ((fd = open(wav_file[channel], O_RDONLY)) < 0) {    fprintf(stderr, _("Cannot open WAV file %s\n"), wav_file[channel]);    return -EINVAL;  }  if (read(fd, &header, sizeof(header)) < (int)sizeof(header)) {    fprintf(stderr, _("Invalid WAV file %s\n"), wav_file[channel]);    goto error;  }    if (header.hdr.magic != WAV_RIFF || header.hdr.type != WAV_WAVE) {    fprintf(stderr, _("Not a WAV file: %s\n"), wav_file[channel]);    goto error;  }  if (header.body.format != LE_SHORT(WAV_PCM_CODE)) {    fprintf(stderr, _("Unsupported WAV format %d for %s\n"),	    LE_SHORT(header.body.format), wav_file[channel]);    goto error;  }  if (header.body.channels != LE_SHORT(1)) {    fprintf(stderr, _("%s is not a mono stream (%d channels)\n"),	    wav_file[channel], LE_SHORT(header.body.channels));     goto error;  }  if (header.body.rate != LE_INT(rate)) {    fprintf(stderr, _("Sample rate doesn't match (%d) for %s\n"),	    LE_INT(header.body.rate), wav_file[channel]);    goto error;  }  if (header.body.sample_bits != LE_SHORT(16)) {    fprintf(stderr, _("Unsupported sample format bits %d for %s\n"),	    LE_SHORT(header.body.sample_bits), wav_file[channel]);    goto error;  }  if (header.chunk.type != WAV_DATA) {    fprintf(stderr, _("Invalid WAV file %s\n"), wav_file[channel]);    goto error;  }  wav_file_size[channel] = LE_INT(header.chunk.length);  close(fd);  return 0; error:  close(fd);  return -EINVAL;}static int setup_wav_file(int chn){  static const char *const wavs[MAX_CHANNELS] = {    "Front_Left.wav",    "Front_Right.wav",    "Rear_Left.wav",    "Rear_Right.wav",    "Front_Center.wav",    "Rear_Center.wav", /* FIXME: should be "Bass" or so */    "Side_Left.wav",    "Side_Right.wav",    "Channel_9.wav",    "Channel_10.wav",    "Channel_11.wav",    "Channel_12.wav",    "Channel_13.wav",    "Channel_14.wav",    "Channel_15.wav",    "Channel_16.wav"  };  if (given_test_wav_file)    return check_wav_file(chn, given_test_wav_file);  else    return check_wav_file(chn, wavs[chn]);}static int read_wav(uint16_t *buf, int channel, int offset, int bufsize){  static FILE *wavfp = NULL;  int size;  if (! wav_file[channel]) {    fprintf(stderr, _("Undefined channel %d\n"), channel);    return -EINVAL;  }  if (offset >= wav_file_size[channel])   return 0; /* finished */  if (! offset) {    if (wavfp)      fclose(wavfp);    wavfp = fopen(wav_file[channel], "r");    if (! wavfp)      return -errno;    if (fseek(wavfp, sizeof(struct wave_header), SEEK_SET) < 0)      return -errno;  }  if (offset + bufsize > wav_file_size[channel])    bufsize = wav_file_size[channel] - offset;  bufsize /= channels;  for (size = 0; size < bufsize; size += 2) {    int chn;    for (chn = 0; chn < channels; chn++) {      if (chn == channel) {	if (fread(buf, 2, 1, wavfp) != 1)	  return size;      }      else	*buf = 0;      buf++;    }  }  return size;}/* *   Transfer method - write only */static int write_buffer(snd_pcm_t *handle, uint8_t *ptr, int cptr){  int err;  while (cptr > 0) {    err = snd_pcm_writei(handle, ptr, cptr);    if (err == -EAGAIN)      continue;    if (err < 0) {      fprintf(stderr, _("Write error: %d,%s\n"), err, snd_strerror(err));      if (xrun_recovery(handle, err) < 0) {	fprintf(stderr, _("xrun_recovery failed: %d,%s\n"), err, snd_strerror(err));	return -1;      }      break;	/* skip one period */    }    ptr += snd_pcm_frames_to_bytes(handle, err);    cptr -= err;  }  return 0;}static int write_loop(snd_pcm_t *handle, int channel, int periods, uint8_t *frames){  double phase = 0;  int    err, n;  if (test_type == TEST_WAV) {    int bufsize = snd_pcm_frames_to_bytes(handle, period_size);    n = 0;    while ((err = read_wav((uint16_t *)frames, channel, n, bufsize)) > 0) {      n += err;      if ((err = write_buffer(handle, frames,			      snd_pcm_bytes_to_frames(handle, err * channels))) < 0)	break;    }    if (buffer_size > n) {      snd_pcm_drain(handle);      snd_pcm_prepare(handle);    }    return err;  }      if (periods <= 0)    periods = 1;  for(n = 0; n < periods; n++) {    if (test_type == TEST_PINK_NOISE)      generate_pink_noise(frames, channel, period_size);    else      generate_sine(frames, channel, period_size, &phase);    if ((err = write_buffer(handle, frames, period_size)) < 0)      return err;  }  if (buffer_size > n * period_size) {    snd_pcm_drain(handle);    snd_pcm_prepare(handle);  }  return 0;}static void help(void){  int k;  printf(	 _("Usage: speaker-test [OPTION]... \n"	   "-h,--help	help\n"	   "-D,--device	playback device\n"	   "-r,--rate	stream rate in Hz\n"	   "-c,--channels	count of channels in stream\n"	   "-f,--frequency	sine wave frequency in Hz\n"	   "-F,--format	sample format\n"	   "-b,--buffer	ring buffer size in us\n"	   "-p,--period	period size in us\n"	   "-P,--nperiods	number of periods\n"	   "-t,--test	pink=use pink noise, sine=use sine wave, wav=WAV file\n"	   "-l,--nloops	specify number of loops to test, 0 = infinite\n"	   "-s,--speaker	single speaker test. Values 1=Left, 2=right, etc\n"	   "-w,--wavfile	Use the given WAV file as a test sound\n"	   "-W,--wavdir	Specify the directory containing WAV files\n"	   "\n"));#if 1  printf(_("Recognized sample formats are:"));  for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {    const char *s = snd_pcm_format_name(k);    if (s)      printf(" %s", s);  }  printf("\n\n");#endif}int main(int argc, char *argv[]) {  snd_pcm_t            *handle;  int                   err, morehelp;  snd_pcm_hw_params_t  *hwparams;  snd_pcm_sw_params_t  *swparams;  uint8_t              *frames;  int                   chn;  double		time1,time2,time3;  unsigned int		n, nloops;  struct   timeval	tv1,tv2;  static const struct option long_option[] = {    {"help",      0, NULL, 'h'},    {"device",    1, NULL, 'D'},    {"rate",      1, NULL, 'r'},    {"channels",  1, NULL, 'c'},    {"frequency", 1, NULL, 'f'},    {"format",    1, NULL, 'F'},    {"buffer",    1, NULL, 'b'},    {"period",    1, NULL, 'p'},    {"nperiods",  1, NULL, 'P'},    {"test",      1, NULL, 't'},    {"nloops",    1, NULL, 'l'},    {"speaker",   1, NULL, 's'},    {"wavfile",   1, NULL, 'w'},    {"wavdir",    1, NULL, 'W'},    {NULL,        0, NULL, 0  },  };#ifdef ENABLE_NLS  setlocale(LC_ALL, "");  textdomain(PACKAGE);#endif  snd_pcm_hw_params_alloca(&hwparams);  snd_pcm_sw_params_alloca(&swparams);   nloops = 0;  morehelp = 0;  printf("\nspeaker-test %s\n\n", SND_UTIL_VERSION_STR);  while (1) {    int c;        if ((c = getopt_long(argc, argv, "hD:r:c:f:F:b:p:P:t:l:s:w:W:", long_option, NULL)) < 0)      break;        switch (c) {    case 'h':      morehelp++;      break;    case 'D':      device = strdup(optarg);      break;    case 'F':      format = snd_pcm_format_value(optarg);      break;    case 'r':      rate = atoi(optarg);      rate = rate < 4000 ? 4000 : rate;      rate = rate > 196000 ? 196000 : rate;      break;    case 'c':      channels = atoi(optarg);      channels = channels < 1 ? 1 : channels;      channels = channels > 1024 ? 1024 : channels;      break;    case 'f':      freq = atoi(optarg);      freq = freq < 50 ? 50 : freq;      freq = freq > 5000 ? 5000 : freq;      break;    case 'b':      buffer_time = atoi(optarg);      buffer_time = buffer_time > 1000000 ? 1000000 : buffer_time;      break;    case 'p':      period_time = atoi(optarg);      period_time = period_time > 1000000 ? 1000000 : period_time;      break;    case 'P':      nperiods = atoi(optarg);      if (nperiods < 2 || nperiods > 1024) {	fprintf(stderr, _("Invalid number of periods %d\n"), nperiods);	exit(1);      }      break;    case 't':      if (*optarg == 'p')	test_type = TEST_PINK_NOISE;      else if (*optarg == 's')	test_type = TEST_SINE;      else if (*optarg == 'w')	test_type = TEST_WAV;      else if (isdigit(*optarg)) {	test_type = atoi(optarg);	if (test_type < TEST_PINK_NOISE || test_type > TEST_WAV) {	  fprintf(stderr, _("Invalid test type %s\n"), optarg);	  exit(1);	}      } else {	fprintf(stderr, _("Invalid test type %s\n"), optarg);	exit(1);      }      break;    case 'l':      nloops = atoi(optarg);      break;    case 's':      speaker = atoi(optarg);      speaker = speaker < 1 ? 0 : speaker;      speaker = speaker > channels ? 0 : speaker;      if (speaker==0) {        fprintf(stderr, _("Invalid parameter for -s option.\n"));        exit(EXIT_FAILURE);      }        break;    case 'w':      given_test_wav_file = optarg;      break;    case 'W':      wav_file_dir = optarg;      break;    default:      fprintf(stderr, _("Unknown option '%c'\n"), c);      exit(EXIT_FAILURE);      break;    }  }  if (morehelp) {    help();    exit(EXIT_SUCCESS);  }  if (test_type == TEST_WAV)    format = SND_PCM_FORMAT_S16_LE; /* fixed format */  printf(_("Playback device is %s\n"), device);  printf(_("Stream parameters are %iHz, %s, %i channels\n"), rate, snd_pcm_format_name(format), channels);  switch (test_type) {  case TEST_PINK_NOISE:    printf(_("Using 16 octaves of pink noise\n"));    break;  case TEST_SINE:    printf(_("Sine wave rate is %.4fHz\n"), freq);    break;  case TEST_WAV:    printf(_("WAV file(s)\n"));    break;  }  while ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {    printf(_("Playback open error: %d,%s\n"), err,snd_strerror(err));    sleep(1);  }  if ((err = set_hwparams(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {    printf(_("Setting of hwparams failed: %s\n"), snd_strerror(err));    snd_pcm_close(handle);    exit(EXIT_FAILURE);  }  if ((err = set_swparams(handle, swparams)) < 0) {    printf(_("Setting of swparams failed: %s\n"), snd_strerror(err));    snd_pcm_close(handle);    exit(EXIT_FAILURE);  }  frames = malloc(snd_pcm_frames_to_bytes(handle, period_size));  if (test_type == TEST_PINK_NOISE)    initialize_pink_noise(&pink, 16);    if (frames == NULL) {    fprintf(stderr, _("No enough memory\n"));    exit(EXIT_FAILURE);  }  if (speaker==0) {    if (test_type == TEST_WAV) {      for (chn = 0; chn < channels; chn++) {	if (setup_wav_file(chn) < 0)	  exit(EXIT_FAILURE);      }    }    for (n = 0; ! nloops || n < nloops; n++) {      gettimeofday(&tv1, NULL);      for(chn = 0; chn < channels; chn++) {	int channel=chn;	if (channels == 4) {	    channel=channels4[chn];	}	if (channels == 6) {	    channel=channels6[chn];	}	if (channels == 8) {	    channel=channels8[chn];	}        printf(" %d - %s\n", channel, gettext(channel_name[channel]));        err = write_loop(handle, channel, ((rate*3)/period_size), frames);        if (err < 0) {          fprintf(stderr, _("Transfer failed: %s\n"), snd_strerror(err));          free(frames);          snd_pcm_close(handle);          exit(EXIT_SUCCESS);        }      }      gettimeofday(&tv2, NULL);      time1 = (double)tv1.tv_sec + ((double)tv1.tv_usec / 1000000.0);      time2 = (double)tv2.tv_sec + ((double)tv2.tv_usec / 1000000.0);      time3 = time2 - time1;      printf(_("Time per period = %lf\n"), time3 );    }  } else {    if (test_type == TEST_WAV) {      if (setup_wav_file(speaker - 1) < 0)	exit(EXIT_FAILURE);    }    printf("  - %s\n", gettext(channel_name[speaker-1]));    err = write_loop(handle, speaker-1, ((rate*5)/period_size), frames);    if (err < 0) {      fprintf(stderr, _("Transfer failed: %s\n"), snd_strerror(err));    }  }  free(frames);  snd_pcm_close(handle);  exit(EXIT_SUCCESS);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -