169 lines
5.2 KiB
C
169 lines
5.2 KiB
C
/**
|
|
* @file SndPam.c
|
|
* @author Rick Chan (cy187lion@sina.com)
|
|
* @brief
|
|
* @version 0.1
|
|
* @date 2020-04-08
|
|
*
|
|
* @copyright Copyright (c) 2020
|
|
*
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <alsa/asoundlib.h>
|
|
#include <pthread.h>
|
|
|
|
#define PERIOD_CNT 16
|
|
#define PERIOD_FRAMES 512
|
|
#define PERIOD_BYTES 2048
|
|
#define BUF_SZ (PERIOD_CNT * PERIOD_FRAMES)
|
|
#define TOTAL_BUF (PERIOD_CNT * PERIOD_BYTES)
|
|
|
|
|
|
void init_pcm(snd_pcm_t *handle, unsigned int rate, unsigned int ch, unsigned int frames, unsigned int periods)
|
|
{
|
|
int err;
|
|
snd_pcm_hw_params_t *hw_params;
|
|
// snd_pcm_sw_params_t *sw_params;
|
|
snd_pcm_uframes_t period_size = frames;
|
|
snd_pcm_uframes_t buffer_size = periods*frames;
|
|
|
|
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
|
|
printf ("cannot allocate hardware parameter structure (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) {
|
|
printf ("cannot initialize hardware parameter structure (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_access (handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
|
printf ("cannot set access type (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_format (handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
|
|
printf ("cannot set sample format (%s)\n",
|
|
snd_strerror (err));
|
|
// exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_rate_near (handle, hw_params, &rate, 0)) < 0) {
|
|
printf ("cannot set sample rate (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_periods_near(handle, hw_params, &periods, NULL)) < 0) {
|
|
printf ("cannot set periods (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_period_size_near(handle, hw_params, &period_size, NULL)) < 0) {
|
|
printf ("cannot set period size (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_buffer_size_near(handle, hw_params, &buffer_size)) < 0) {
|
|
printf ("cannot set buffer size (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params_set_channels (handle, hw_params, 2)) < 0) {
|
|
printf ("cannot set channel count (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_hw_params (handle, hw_params)) < 0) {
|
|
printf ("cannot set hardware parameters (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
|
|
/*snd_pcm_sw_params_alloca (&sw_params);
|
|
|
|
if ((err = snd_pcm_sw_params_current(handle, sw_params)) < 0) {
|
|
printf ("cannot get current software parameters (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_sw_params_set_start_threshold (handle, sw_params, 0)) < 0) {
|
|
printf ("cannot set threshold (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
if ((err = snd_pcm_sw_params (handle, sw_params)) < 0) {
|
|
printf ("cannot set software parameters (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}*/
|
|
if ((err = snd_pcm_prepare (handle)) < 0) {
|
|
printf ("cannot prepare audio interface for use (%s)\n",
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
}
|
|
|
|
snd_pcm_t* init_playback(char output[], unsigned int rate, unsigned int ch, unsigned int frames, unsigned int periods)
|
|
{
|
|
int err;
|
|
snd_pcm_t *playback_handle;
|
|
|
|
if ((err = snd_pcm_open (&playback_handle, output, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
|
|
printf ("cannot open audio device %s (%s)\n",
|
|
output,
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
init_pcm(playback_handle, rate, ch, frames, periods);
|
|
return playback_handle;
|
|
}
|
|
|
|
#if 0
|
|
snd_pcm_t* init_capture(char input[])
|
|
{
|
|
int err;
|
|
snd_pcm_t *capture_handle;
|
|
|
|
if ((err = snd_pcm_open (&capture_handle, input, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
|
|
printf ("cannot open audio device %s (%s)\n",
|
|
input,
|
|
snd_strerror (err));
|
|
exit (1);
|
|
}
|
|
init_pcm(capture_handle);
|
|
return capture_handle;
|
|
}
|
|
#endif
|
|
|
|
int main (int argc, char *argv[])
|
|
{
|
|
snd_pcm_t* playback_handle;
|
|
unsigned int rate;
|
|
unsigned int ch;
|
|
unsigned int frames;
|
|
unsigned int periods;
|
|
|
|
if (2==argc) {
|
|
if (0==strcmp("-v", argv[1]))
|
|
printf ("SndPam Version 1.0\r\n");
|
|
|
|
if (0==strcmp("-h", argv[1]))
|
|
printf ("SndPam <device>\r\nExp: SndPam plughw:0,0 <rate> <ch> <frames> <periods>\r\n");
|
|
|
|
exit (0);
|
|
}
|
|
|
|
if (6!=argc) {
|
|
printf ("SndPam <device>\r\nExp: SndPam plughw:0,0 <rate> <ch> <frames> <periods>\r\n");
|
|
exit (0);
|
|
}
|
|
|
|
sscanf(argv[2], "%u", &rate);
|
|
sscanf(argv[3], "%u", &ch);
|
|
sscanf(argv[4], "%u", &frames);
|
|
sscanf(argv[5], "%u", &periods);
|
|
printf("Open With R=%u, CH=%u, Frames=%u, Periods=%u.\r\n", rate, ch, frames, periods);
|
|
playback_handle = init_playback (argv[1], rate, ch, frames, periods);
|
|
exit (0);
|
|
}
|