做下面这些工作的前提先把 alsa 的库安装好:
sudo apt-get install libasound2-dev
查找设备名:
API 库使用逻辑设备名而不是设备文件。设备名字可以是真实的硬件名字也可以是插件名字。硬件名
字使用hw:i,j这样的格式。其中i是卡号,j是这块声卡上的设备号。第一个声音设备是hw:0,0.这个
我的usb拾音器是4麦的,也统称的4通道
我的设备是16K的采样率(16000个数据/s), 根据自己的设备来, 填错了, 就会小姐姐变大叔
我的是小端 16位一个数据
设置每路通道每次采集128个数据
录制后我用测试
Code:
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#include <pthread.h>
using namespace std;
#define REC_DEV "hw:1,0"
#define CHANNELS 4
#define RATE 16000
#define FRAMES 128
#define BITE 2
#define PATH "../bin/"
#define NAMELANGTH 128
bool g_bRecord;
bool g_bMainON;
FILE* g_pFile[CHANNELS];
void* run(void* args)
{
#define ALSA_PCM_NEW_HW_PARAMS_API
char cNamePath[NAMELANGTH];
memset(cNamePath, 0, sizeof(char) * NAMELANGTH);
for(int i = 0; i < CHANNELS; i++)
{
sprintf(cNamePath,"%sData-%02d.pcm",PATH, i);
if((g_pFile[i] = fopen(cNamePath, "w")) == NULL)
{
printf("Read local pcm path failed!\n");
exit(0);
}
}
int rc; //一个int变量 ,用来存放 snd_pcm_open(访问硬件)的返回值
int size; //一个int变量
snd_pcm_t * handle; // 一个指向snd_pcm_t的指针
snd_pcm_hw_params_t * params; // 一个指向 snd_pcm_hw_params_t的指针
unsigned int val = RATE; // 无符号整型变量 ,用来存放录音时候的采样率
snd_pcm_uframes_t frames = FRAMES; // snd_pcm_uframes_t 型变量
int channels = CHANNELS;
int dir; // 整型变量
char * buffer; // 一个字符型指针
/* open PCM device for recording (capture). */
// 访问硬件,并判断硬件是否访问成功
rc = snd_pcm_open(&handle, REC_DEV, SND_PCM_STREAM_CAPTURE,0);
if( rc < 0 )
{
fprintf(stderr,
"unable to open pcm device: %sn",
snd_strerror(rc));
exit(1);
}
/* allocate a hardware parameters object */
// 分配一个硬件变量对象
snd_pcm_hw_params_alloca(¶ms);
/* fill it with default values. */
// 按照默认设置对硬件对象进行设置
snd_pcm_hw_params_any(handle,params);
/* set the desired hardware parameters */
/* interleaved mode 设置数据为交叉模式*/
snd_pcm_hw_params_set_access(handle,params,
SND_PCM_ACCESS_RW_INTERLEAVED);
/* signed 16-bit little-endian format */
// 设置数据编码格式为PCM、有符号、16bit、LE格式
snd_pcm_hw_params_set_format(handle,params,
SND_PCM_FORMAT_S16_LE);
/* two channels(stereo) */
// 设置单声道
snd_pcm_hw_params_set_channels(handle,params,channels);
/* sampling rate */
// 设置采样率
snd_pcm_hw_params_set_rate_near(handle,params,&val,&dir);
/* set period size */
// 周期长度(帧数)
frames = 32;
snd_pcm_hw_params_set_period_size_near(handle,params,&frames,&dir);
/* write parameters to the driver */
// 将配置写入驱动程序中
// 判断是否已经配置正确
rc = snd_pcm_hw_params(handle,params);
if ( rc < 0 )
{
fprintf(stderr,
"unable to set hw parameters: %sn",
snd_strerror(rc));
exit(1);
}
/* use a buffer large enough to hold one period */
// 配置一个缓冲区用来缓冲数据,缓冲区要足够大,此处看意思应该是只配置了
// 够两个声道用的缓冲内存
snd_pcm_hw_params_get_period_size(params,&frames,&dir);
size = frames * BITE * channels; /* 2 bytes/sample, 2channels */
buffer = ( char * ) malloc(size);
/* loop for 5 seconds */
// 记录五秒长的声音
snd_pcm_hw_params_get_period_time(params, &val, &dir);
printf("revord start!\n");
while(g_bRecord)
{
rc = snd_pcm_readi(handle,buffer,frames);
if ( rc == -EPIPE )
{
/* EPIPE means overrun */
fprintf(stderr,"overrun occuredn");
snd_pcm_prepare(handle);
}
else if ( rc < 0 )
{
fprintf(stderr,"error from read: %sn",
snd_strerror(rc));
}
else if ( rc != (int)frames)
{
fprintf(stderr,"short read, read %d framesn",rc);
}
// // 将音频数据写入文件
for(int i = 0; i<frames * channels; i+=channels)
{
for(int j = 0; j<channels;j++)
{
fwrite(buffer + (i+j)*BITE, BITE, 1, g_pFile[j]);
}
}
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
for(int i = 0; i<CHANNELS; i++)
{
fclose(g_pFile[i]);
}
printf("record over!\n");
}
int main(int argc, char *argv[])
{
g_bRecord = true;
g_bMainON = true;
pthread_t stThread;
int ret = pthread_create(&stThread, NULL, run, NULL);
if (ret != 0)
{
printf("pthread_create error: error_code=%d\n", ret);
}
while(getchar() != 'c')
{
g_bRecord = false;
}
while(g_bMainON);
exit (0);
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.5.1)
project(MakePCM)
set(CMAKE_CXX_STANDARD 11)
set(SOURCE_FILES
./src/main.cpp
)
set(INC_DIR ./3rdpart/include)
set(LINK_DIR ./3rdpart/lib)
include_directories(${INC_DIR})
link_directories(${LINK_DIR})
link_libraries(
asound
pthread
)
add_executable(MakePCM ${SOURCE_FILES})
target_link_libraries(MakePCM
asound
pthread
)
网友评论