//File : sndwav_common.c
//Author : Loon <sepnic@gmail.com>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <alsa/asoundlib.h>
#include "sndwav_common.h"
int SNDWAV_P_GetFormat(WAVContainer_t *wav, snd_pcm_format_t *snd_format)
{
if (LE_SHORT(wav->format.format) != WAV_FMT_PCM)
return -1;
switch (LE_SHORT(wav->format.sample_length)) {
case 16:
*snd_format = SND_PCM_FORMAT_S16_LE;
break;
case 8:
*snd_format = SND_PCM_FORMAT_U8;
break;
default:
*snd_format = SND_PCM_FORMAT_UNKNOWN;
break;
}
return 0;
}
ssize_t SNDWAV_ReadPcm(SNDPCMContainer_t *sndpcm, size_t rcount)
{
ssize_t r;
size_t result = 0;
size_t count = rcount;
uint8_t *data = sndpcm->data_buf;
if (count != sndpcm->chunk_size) {
count = sndpcm->chunk_size;
}
while (count > 0) {
r = snd_pcm_readi(sndpcm->handle, data, count);
if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
snd_pcm_wait(sndpcm->handle, 1000);
} else if (r == -EPIPE) {
snd_pcm_prepare(sndpcm->handle);
fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>/n");
} else if (r == -ESTRPIPE) {
fprintf(stderr, "<<<<<<<<<<<<<<< Need suspend >>>>>>>>>>>>>>>/n");
} else if (r < 0) {
fprintf(stderr, "Error snd_pcm_writei: [%s]", snd_strerror(r));
exit(-1);
}
if (r > 0) {
result += r;
count -= r;
data += r * sndpcm->bits_per_frame / 8;
}
}
return rcount;
}
ssize_t SNDWAV_WritePcm(SNDPCMContainer_t *sndpcm, size_t wcount)
{
ssize_t r;
ssize_t result = 0;
uint8_t *data = sndpcm->data_buf;
if (wcount < sndpcm->chunk_size) {
snd_pcm_format_set_silence(sndpcm->format,
data + wcount * sndpcm->bits_per_frame / 8,
(sndpcm->chunk_size - wcount) * sndpcm->channels);
wcount = sndpcm->chunk_size;
}
while (wcount > 0) {
r = snd_pcm_writei(sndpcm->handle, data, wcount);
if (r == -EAGAIN || (r >= 0 && (size_t)r < wcount)) {
snd_pcm_wait(sndpcm->handle, 1000);
} else if (r == -EPIPE) {
snd_pcm_prepare(sndpcm->handle);
fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>/n");
} else if (r == -ESTRPIPE) {
fprintf(stderr, "<<<<<<<<<<<<<<< Need suspend >>>>>>>>>>>>>>>/n");
} else if (r < 0) {
fprintf(stderr, "Error snd_pcm_writei: [%s]", snd_strerror(r));
exit(-1);
}
if (r > 0) {
result += r;
wcount -= r;
data += r * sndpcm->bits_per_frame / 8;
}
}
return result;
}
int SNDWAV_SetParams(SNDPCMContainer_t *sndpcm, WAVContainer_t *wav)
{
snd_pcm_hw_params_t *hwparams;
snd_pcm_format_t format;
uint32_t exact_rate;
uint32_t buffer_time, period_time;
/* Allocate the snd_pcm_hw_params_t structure on the stack. */
snd_pcm_hw_params_alloca(&hwparams);
/* Init hwparams with full configuration space */
if (snd_pcm_hw_params_any(sndpcm->handle, hwparams) < 0) {
fprintf(stderr, "Error snd_pcm_hw_params_any/n");
goto ERR_SET_PARAMS;
}
if (snd_pcm_hw_params_set_access(sndpcm->handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
fprintf(stderr, "Error snd_pcm_hw_params_set_access/n");
goto ERR_SET_PARAMS;
}
/* Set sample format */
if (SNDWAV_P_GetFormat(wav, &format) < 0) {
fprintf(stderr, "Error get_snd_pcm_format/n");
goto ERR_SET_PARAMS;
}
if (snd_pcm_hw_params_set_format(sndpcm->handle, hwparams, format) < 0) {
fprintf(stderr, "Error snd_pcm_hw_params_set_format/n");
goto ERR_SET_PARAMS;
}
sndpcm->format = format;
/* Set number of channels */
if (snd_pcm_hw_params_set_channels(sndpcm->handle, hwparams, LE_SHORT(wav->format.channels)) < 0) {
fprintf(stderr, "Error snd_pcm_hw_params_set_channels/n");
goto ERR_SET_PARAMS;
}
sndpcm->channels = LE_SHORT(wav->format.channels);
/* Set sample rate. If the exact rate is not supported */
/* by the hardware, use nearest possible rate. */
exact_rate = LE_INT(wav->format.sample_rate);
if (snd_pcm_hw_params_set_rate_near(sndpcm->handle, hwparams, &exact_rate, 0) < 0) {
fprintf(stderr, "Error snd_pcm_hw_params_set_rate_near/n");
goto ERR_SET_PARAMS;
}
if (LE_INT(wav->format.sample_rate) != exact_rate) {
fprintf(stderr, "The rate %d Hz is not supported by your hardware./n ==> Using %d Hz instead./n",
LE_INT(wav->format.sample_rate), exact_rate);
}
if (snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0) < 0) {
fprintf(stderr, "Error snd_pcm_hw_params_get_buffer_time_max/n");
goto ERR_SET_PARAMS;
}
if (buffer_time > 500000) buffer_time = 500000;
period_time = buffer_time / 4;
if (snd_pcm_hw_params_set_buffer_time_near(sndpcm->handle, hwparams, &buffer_time, 0) < 0) {
fprintf(stderr, "Error snd_pcm_hw_params_set_buffer_time_near/n");
goto ERR_SET_PARAMS;
}
if (snd_pcm_hw_params_set_period_time_near(sndpcm->handle, hwparams, &period_time, 0) < 0) {
fprintf(stderr, "Error snd_pcm_hw_params_set_period_time_near/n");
goto ERR_SET_PARAMS;
}
/* Set hw params */
if (snd_pcm_hw_params(sndpcm->handle, hwparams) < 0) {
fprintf(stderr, "Error snd_pcm_hw_params(handle, params)/n");
goto ERR_SET_PARAMS;
}
snd_pcm_hw_params_get_period_size(hwparams, &sndpcm->chunk_size, 0);
snd_pcm_hw_params_get_buffer_size(hwparams, &sndpcm->buffer_size);
if (sndpcm->chunk_size == sndpcm->buffer_size) {
fprintf(stderr, ("Can't use period equal to buffer size (%lu == %lu)/n"), sndpcm->chunk_size, sndpcm->buffer_size);
goto ERR_SET_PARAMS;
}
sndpcm->bits_per_sample = snd_pcm_format_physical_width(format);
sndpcm->bits_per_frame = sndpcm->bits_per_sample * LE_SHORT(wav->format.channels);
sndpcm->chunk_bytes = sndpcm->chunk_size * sndpcm->bits_per_frame / 8;
/* Allocate audio data buffer */
sndpcm->data_buf = (uint8_t *)malloc(sndpcm->chunk_bytes);
if (!sndpcm->data_buf) {
fprintf(stderr, "Error malloc: [data_buf]/n");
goto ERR_SET_PARAMS;
}
return 0;
ERR_SET_PARAMS:
return -1;
}
没有合适的资源?快使用搜索试试~ 我知道了~
alsa.zip_alsa record_alsa播放_snd
共6个文件
c:4个
h:2个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 12 浏览量
2022-09-20
19:54:05
上传
评论
收藏 7KB ZIP 举报
温馨提示
基于ALSA的WAV播放和录音程序完整源码,程序包包含四个部分:WAV Parser、SND Common、Playback和Record。WAV Parser是对WAV文件的分析和封装,这里只针对Standard WAV File;SND Common是Playback 和Record共同操作,如SetParams、ReadPCM和WritePCM等;Playback和Record就分别是播放录音的主体了。原理很 简单,以Playback为例:从WAV文件读取PCM数据,通过I2S或AC97依次送到Audio Codec。
资源推荐
资源详情
资源评论
收起资源包目录
alsa.zip (6个子文件)
alsa
wav_parser.c 4KB
sndwav_common.h 818B
wav_parser.h 3KB
lplay.c 3KB
sndwav_common.c 6KB
lrecord.c 4KB
共 6 条
- 1
资源评论
邓凌佳
- 粉丝: 76
- 资源: 1万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- SpringBoot3.3 实现停止/重启定时任务的代码
- vgg-generated-120.i
- stk8329 acc datasheet
- CT7117体温传感器驱动代码
- 基于51单片机和HC-05蓝牙模块、Lcd模块、DS18B20温度传感器模块利用串口通信进行环境监测源码全部资料(高分项目)
- MID国家编码表 MMSI国家编码表 MMSI-MID 国家编码表 AIS 国家编码表
- 基于51单片机和HC-05蓝牙模块、Lcd模块、DS18B20温度传感器模块利用串口通信进行环境监测(完整高分项目代码)
- c05300 amoled datasheet
- ats3089 datasheet
- 矩芯 ats3085s datasheet
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功