Alsa 播放从 CAN FD 获取的音频
Alsa plays audio get from CAN FD
我正在尝试使用 Alsa 库将我从 CAN FD 通信中获得的音频复制到我的耳机中。我不太明白如何正确配置 Alsa 的参数,以便能够听到我从 CAN FD 获得的声音。
static char *device = "plughw:0,0"; /* playback device */
static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; /* sample format */
static unsigned int rate = 16000; /* stream rate */
static unsigned int channels = 1; /* count of channels */
static unsigned int buffer_time = 40000; /* ring buffer length in us */
static unsigned int period_time = 120000; /* period time in us */
static int resample = 1; /* enable alsa-lib resampling */
static int period_event = 0; /* produce poll event after each period */
int size;
while (1) {
do {
nbytes = read(s, &frame, sizeof(struct canfd_frame));
} while (nbytes == 0);
for (x = 0; x < 64; x = x + 2) {
buffer[a] = ((uint32_t) frame.data[x] << 8)
| ((uint32_t) (frame.data[x + 1]));
a++;
}
//err=snd_pcm_writei(handle,buffer,32);
//printf("Datos = %d\n", err);
memcpy(total1 + i * 32, buffer, 32 * sizeof(uint32_t));
i++;
a = 0;
if (i == 500) {
buffer_length=16000;
ptr = total1;
while(buffer_length > 0){
err = snd_pcm_writei(handle, ptr, 16000);
printf("Datos = %d\n", err);
snd_pcm_avail_delay(handle, &availp, &delayp);
//printf("available frames =%ld delay = %ld z = %d\n", availp, delayp, z);
if (err == -EAGAIN)
continue;
if(err < 0){
err=snd_pcm_recover(handle, err, 1);
}
else{
ptr += err * channels;
buffer_length -= err;
z++;
}
if(err<0){
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
break;
}
}
i = 0;
}
这是我的代码的一部分,我认为不值得发布整个代码。我不明白我应该给 buffer_time、period_time 哪些值,以及如何能够实时收听我通过 CAN FD 获得的信息。我正在使用 snd_pcm_writei,插入一个缓冲区,其中填充了一些从 CAN FD 获得的样本。我不知道我应该给缓冲区和“帧”变量设置多大的大小,这是另一个我不太了解的变量,尽管我已经阅读了一些相关内容。
知道我应该如何配置我的系统吗? (buffer_time, period_time, buffer_size, 帧,...)
我尝试过使用不同的缓冲区和帧大小,但我认为我不明白它是如何正常工作的。如何计算 snd_pcm_writei() 的帧和缓冲区的大小,以便实时收听音频?
我应该使用两个不同的线程吗?一个用 CAN FD 信息创建缓冲区,另一个处理缓冲区和音频输出?
提前致谢,
安德.
我终于可以通过耳机听到自己的声音了。我已经更改了我以前的配置 posted,以便用我从 CAN FD 获得的数据对其进行同步。我将 post 部分代码放在这里,以防有人需要示例。必须处理此类缓冲区的最重要部分是处理填充时间和通信时间。相应地处理时间和配置 Alsa 参数可以更容易地处理缓冲区。
static char *device = "plughw:0,0"; /* playback device */
static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; /* sample format */
static unsigned int rate = 22000; /* stream rate */
static unsigned int channels = 1; /* count of channels */
static unsigned int buffer_time = 1000; /* ring buffer length in us */
static unsigned int period_time = 10000; /* period time in us */
static int resample = 1; /* enable alsa-lib resampling */
static int period_event = 0; /* produce poll event after each period */
int size;
static snd_pcm_sframes_t buffer_size;
static snd_pcm_sframes_t period_size;
static snd_output_t *output = NULL;
snd_pcm_sframes_t delayp;
snd_pcm_sframes_t availp;
snd_pcm_uframes_t frames;
static void write_loop(snd_pcm_t *handle) {
uint32_t *buffer = malloc(16000 * sizeof(uint32_t));
uint32_t *total1 = malloc(16000 * sizeof(uint32_t)); // array to hold the result
while (1) {
do {
nbytes = read(s, &frame, sizeof(struct canfd_frame));
} while (nbytes == 0);
for (x = 0; x < 64;x = x + 2) {
buffer[a] = ((uint32_t) frame.data[x] << 8)
| ((uint32_t) (frame.data[x + 1]));
//buffer[a]=frame.data[x];
a++;
}
i++;
if (i == 250) {
memcpy(total1, buffer, 16000 * sizeof(uint32_t));
//printf("Address = %lu \n",(unsigned long)total1);
flag = 1;
buffer_length = 16000;
i = 0;
a = 0;
}
if (flag == 1) {
while(buffer_length > 0) {
snd_pcm_prepare(handle);
err = snd_pcm_writei(handle, total1, buffer_length);
//printf("Datos = %d\n", err);
snd_pcm_avail_delay(handle, &availp, &delayp);
//printf("available frames =%ld delay = %ld\n",availp,delayp);
if (err == -EAGAIN)
continue;
if (err < 0) {
err = snd_pcm_recover(handle, err, 1);
} else {
ptr += err * channels;
buffer_length -= err;
z++;
}
if (err < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
break;
}
}
flag = 0;
}
}
}
我正在尝试使用 Alsa 库将我从 CAN FD 通信中获得的音频复制到我的耳机中。我不太明白如何正确配置 Alsa 的参数,以便能够听到我从 CAN FD 获得的声音。
static char *device = "plughw:0,0"; /* playback device */
static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; /* sample format */
static unsigned int rate = 16000; /* stream rate */
static unsigned int channels = 1; /* count of channels */
static unsigned int buffer_time = 40000; /* ring buffer length in us */
static unsigned int period_time = 120000; /* period time in us */
static int resample = 1; /* enable alsa-lib resampling */
static int period_event = 0; /* produce poll event after each period */
int size;
while (1) {
do {
nbytes = read(s, &frame, sizeof(struct canfd_frame));
} while (nbytes == 0);
for (x = 0; x < 64; x = x + 2) {
buffer[a] = ((uint32_t) frame.data[x] << 8)
| ((uint32_t) (frame.data[x + 1]));
a++;
}
//err=snd_pcm_writei(handle,buffer,32);
//printf("Datos = %d\n", err);
memcpy(total1 + i * 32, buffer, 32 * sizeof(uint32_t));
i++;
a = 0;
if (i == 500) {
buffer_length=16000;
ptr = total1;
while(buffer_length > 0){
err = snd_pcm_writei(handle, ptr, 16000);
printf("Datos = %d\n", err);
snd_pcm_avail_delay(handle, &availp, &delayp);
//printf("available frames =%ld delay = %ld z = %d\n", availp, delayp, z);
if (err == -EAGAIN)
continue;
if(err < 0){
err=snd_pcm_recover(handle, err, 1);
}
else{
ptr += err * channels;
buffer_length -= err;
z++;
}
if(err<0){
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
break;
}
}
i = 0;
}
这是我的代码的一部分,我认为不值得发布整个代码。我不明白我应该给 buffer_time、period_time 哪些值,以及如何能够实时收听我通过 CAN FD 获得的信息。我正在使用 snd_pcm_writei,插入一个缓冲区,其中填充了一些从 CAN FD 获得的样本。我不知道我应该给缓冲区和“帧”变量设置多大的大小,这是另一个我不太了解的变量,尽管我已经阅读了一些相关内容。
知道我应该如何配置我的系统吗? (buffer_time, period_time, buffer_size, 帧,...) 我尝试过使用不同的缓冲区和帧大小,但我认为我不明白它是如何正常工作的。如何计算 snd_pcm_writei() 的帧和缓冲区的大小,以便实时收听音频?
我应该使用两个不同的线程吗?一个用 CAN FD 信息创建缓冲区,另一个处理缓冲区和音频输出?
提前致谢, 安德.
我终于可以通过耳机听到自己的声音了。我已经更改了我以前的配置 posted,以便用我从 CAN FD 获得的数据对其进行同步。我将 post 部分代码放在这里,以防有人需要示例。必须处理此类缓冲区的最重要部分是处理填充时间和通信时间。相应地处理时间和配置 Alsa 参数可以更容易地处理缓冲区。
static char *device = "plughw:0,0"; /* playback device */
static snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE; /* sample format */
static unsigned int rate = 22000; /* stream rate */
static unsigned int channels = 1; /* count of channels */
static unsigned int buffer_time = 1000; /* ring buffer length in us */
static unsigned int period_time = 10000; /* period time in us */
static int resample = 1; /* enable alsa-lib resampling */
static int period_event = 0; /* produce poll event after each period */
int size;
static snd_pcm_sframes_t buffer_size;
static snd_pcm_sframes_t period_size;
static snd_output_t *output = NULL;
snd_pcm_sframes_t delayp;
snd_pcm_sframes_t availp;
snd_pcm_uframes_t frames;
static void write_loop(snd_pcm_t *handle) {
uint32_t *buffer = malloc(16000 * sizeof(uint32_t));
uint32_t *total1 = malloc(16000 * sizeof(uint32_t)); // array to hold the result
while (1) {
do {
nbytes = read(s, &frame, sizeof(struct canfd_frame));
} while (nbytes == 0);
for (x = 0; x < 64;x = x + 2) {
buffer[a] = ((uint32_t) frame.data[x] << 8)
| ((uint32_t) (frame.data[x + 1]));
//buffer[a]=frame.data[x];
a++;
}
i++;
if (i == 250) {
memcpy(total1, buffer, 16000 * sizeof(uint32_t));
//printf("Address = %lu \n",(unsigned long)total1);
flag = 1;
buffer_length = 16000;
i = 0;
a = 0;
}
if (flag == 1) {
while(buffer_length > 0) {
snd_pcm_prepare(handle);
err = snd_pcm_writei(handle, total1, buffer_length);
//printf("Datos = %d\n", err);
snd_pcm_avail_delay(handle, &availp, &delayp);
//printf("available frames =%ld delay = %ld\n",availp,delayp);
if (err == -EAGAIN)
continue;
if (err < 0) {
err = snd_pcm_recover(handle, err, 1);
} else {
ptr += err * channels;
buffer_length -= err;
z++;
}
if (err < 0) {
printf("snd_pcm_writei failed: %s\n", snd_strerror(err));
break;
}
}
flag = 0;
}
}
}