Linux下非常实用的asla卡录音小程序

#include <pthread.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

#include <stdint.h>

#include <alsa/asoundlib.h>

#include <math.h>

#define BUFFERSIZE 4096

#define PERIOD_SIZE 1024

#define PERIODS 2

#define SAMPLE_RATE 44100

#define CHANNELS 2

#define FSIZE 2*CHANNELS

/* Use the newer ALSA API */

#define ALSA_PCM_NEW_HW_PARAMS_API

enum MYTHREAD_STATUS {

BGN,

RUNNING,

WAITTING,

CAPTRUING,

STOP,

};

static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;

static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

static enum MYTHREAD_STATUS trigger_thread_status = BGN;

static enum MYTHREAD_STATUS audio_capture_thread_status = BGN;

void audio_capture(uint8_t *p_buffer, uint32_t buffer_size);

// This function will be called by another thread to trigger the audio recording

void audio_recording_trigger(void);

void audio_capture(uint8_t *p_buffer, uint32_t buffer_size)

{

long loops; //define the record time.

int rc; //return code.

int size;

snd_pcm_t *handle;

snd_pcm_hw_params_t *params;

unsigned int val;

int dir;

snd_pcm_uframes_t frames;

char *buffer;

int err;

char *file;

int fd;

file = "output.raw";

fd = open(file,O_WRONLY|O_CREAT,0777);

if( fd ==-1) {

printf("open file:%s fail.\n",file);

exit(1);

}

/* Open PCM device for recording (capture). */

err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);

if (err < 0) {

fprintf(stderr,"unable to open pcm device: %s\n",

snd_strerror(err));

exit(1);

}

/* Allocate a hardware parameters object. */

snd_pcm_hw_params_alloca(&params);

/* Fill it in with default values. */

err=snd_pcm_hw_params_any(handle, params);

if (err < 0) {

fprintf(stderr, "Can not configure this PCM device: %s\n",

snd_strerror(err));

exit(1);

}

/* Set the desired hardware parameters. */

/* Interleaved mode */

err=snd_pcm_hw_params_set_access(handle, params,SND_PCM_ACCESS_RW_INTERLEAVED);

if (err < 0) {

fprintf(stderr,

"Failed to set PCM device to interleaved: %s\n",

snd_strerror(err));

exit(1);

}

/* Signed 16-bit little-endian format */

err=snd_pcm_hw_params_set_format(handle, params,SND_PCM_FORMAT_S16_LE);

if (err < 0) {

fprintf(stderr,

"Failed to set PCM device to 16-bit signed PCM: %s\n",

snd_strerror(err));

exit(1);

}

/* One channels (mono) */

/* two channels(stereo) */

// 设置单声道/多声道

err=snd_pcm_hw_params_set_channels(handle, params, CHANNELS);

if (err < 0) {

fprintf(stderr, "Failed to set PCM device to mono: %s\n",

snd_strerror(err));

exit(1);

}

/* 44100 bits/second sampling rate (CD quality) */

val = SAMPLE_RATE;

err=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);

if (err < 0) {

fprintf(stderr, "Failed to set PCM device to sample rate =%d: %s\n",

val,snd_strerror(err));

exit(1);

}

/* Set buffer time 500000. */

unsigned int buffer_time, period_time;

snd_pcm_hw_params_get_buffer_time_max(params, &buffer_time, 0);

if ( buffer_time >500000)

buffer_time = 500000;

period_time = buffer_time / 4;

err = snd_pcm_hw_params_set_buffer_time_near(handle, params, &buffer_time, 0);

if (err < 0) {

fprintf(stderr, "Failed to set PCM device to buffer time =%d: %s\n",

buffer_time,snd_strerror(err));

exit(1);

}

err = snd_pcm_hw_params_set_period_time_near(handle, params, &period_time, 0);

if (err < 0) {

fprintf(stderr, "Failed to set PCM device to period time =%d: %s\n",

period_time,snd_strerror(err));

exit(1);

}

/* Write the parameters to the driver */

err = snd_pcm_hw_params(handle, params);

if (err < 0) {

fprintf(stderr,"unable to set hw parameters: %s\n",

snd_strerror(err));

exit(1);

}

/* Use a buffer large enough to hold one period */

snd_pcm_hw_params_get_period_size(params,&frames, &dir);

size = frames * FSIZE; /* 2 bytes/sample, 1 channels */

buffer = (char *) malloc(size);

printf("period size = %d frames\n", (int)frames);

printf("read buffer size = %d\n",size);

/* We want to loop for 10 seconds */

snd_pcm_hw_params_get_period_time(params, &val, &dir);

printf("period time is: %d\n",val);

loops = 10000000 / val;

/*print alsa config parameter*/

snd_pcm_hw_params_get_buffer_time(params, &val, &dir);

printf("buffer time = %d us\n", val);

snd_pcm_hw_params_get_buffer_size(params, (snd_pcm_uframes_t *) &val);

printf("buffer size = %d frames\n", val);

snd_pcm_hw_params_get_periods(params, &val, &dir);

printf("periods per buffer = %d frames\n", val);

while (loops > 0) {

loops--;

//printf("loops = %ld\n", loops);

rc = snd_pcm_readi(handle, buffer, frames);

if (rc == -EPIPE) {

// EPIPE means overrun

fprintf(stderr, "overrun occurred\n");

err=snd_pcm_prepare(handle);

if( err <0) {

fprintf(stderr, "Failed to recover form overrun : %s\n",

snd_strerror(err));

exit(1);

}

} else if (rc < 0) {

fprintf(stderr,"error from read: %s\n",snd_strerror(rc));

exit(1);

} else if (rc != (int)frames) {

fprintf(stderr, "short read, read %d frames\n", rc);

}

rc = write(fd, buffer, size);

if (rc <0) {

perror("fail to write to audio file\n");

}

}

printf("capture thread end.\n");

close(fd);

snd_pcm_drain(handle);

snd_pcm_close(handle);

free(buffer);

}

void *trigger_func(void *);

void *audio_capture_func(void *);

int main(int argc, char *argv[])

{

// TODO: Implement the main function

pthread_t thread1, thread2;

void *thread1_return, *thread2_return;

int wait_thread_end;

pthread_create(&thread1, NULL, trigger_func, NULL);

pthread_create(&thread2, NULL, audio_capture_func, NULL);

wait_thread_end = pthread_join( thread1, &thread1_return );

if( wait_thread_end != 0 ) {

printf("trigger thread call pthread_jion return Error.\n");

} else {

printf("trigger thread call pthread_join success.\n");

}

trigger_thread_status = STOP;

pthread_cond_signal(&cond);

wait_thread_end = pthread_join( thread2, &thread2_return);

if( wait_thread_end != 0 ) {

printf("capture audio thread call pthread_join return Error!\n");

} else {

printf("capture audio thread call pthread_join return success\n");

}

return 0;

}

void *audio_capture_func(void *arg)

{

(void)pthread_mutex_unlock(&mtx); //释放锁

audio_capture_thread_status = BGN;

while (1) {

audio_capture_thread_status = RUNNING;

pthread_mutex_lock(&mtx);

printf("wait triger thread command.\n");

audio_capture_thread_status = WAITTING;

pthread_cond_wait(&cond, &mtx);

audio_capture_thread_status = CAPTRUING;

if (trigger_thread_status == STOP) {

printf("audio_capture_thread end.\n");

pthread_mutex_unlock(&mtx);

break;

}

audio_capture(NULL, 0);

audio_capture_thread_status = WAITTING;

pthread_mutex_unlock(&mtx);

}

return (void *)123;

}

static void print_help(void)

{

printf("Please press a key:\n");

printf(" c : capture audio.\n" );

printf(" e : exit thread.\n");

}

void *trigger_func(void *arg)

{

audio_recording_trigger();

return (void *)456;

}

void audio_recording_trigger(void)

{

// TODO: Implement the audio recording trigger

int i;

print_help();

trigger_thread_status = RUNNING;

while (1) {

i = getchar();

if (i == 'c') {

printf("tell audio capture thread work now.\n");

if (audio_capture_thread_status == CAPTRUING) {

printf("now thread is capture audio.\n");

}

pthread_cond_signal(&cond);

sleep(1);

continue;

} else if (i == 'e') {

trigger_thread_status = STOP;

pthread_cond_signal(&cond);

break;

} else {

printf("Not use this command.\n");

sleep(1);

}

}

printf( "tringger thread end.\n");

}

编译的Makefile:

CC=gcc

CCFLAGS=-g -Wall

LDFLAGS=-lasound -lpthread -lm

all:recordc

recordc:audio.c

(CC) audio.c (CCFLAGS) $(LDFLAGS) -o audio

clean:

rm audio output.raw

相关推荐
..过云雨11 分钟前
04.【Linux系统编程】基础开发工具2(makefile、进度条程序实现、版本控制器Git、调试器gdb/cgdb的使用)
linux·笔记·学习
zzzsde22 分钟前
【Linux】初识Linux
linux·运维·服务器
渡我白衣31 分钟前
Linux网络:应用层协议http
linux·网络·http
pofenx44 分钟前
使用nps创建隧道,进行内网穿透
linux·网络·内网穿透·nps
Ronin3051 小时前
【Linux系统】单例式线程池
linux·服务器·单例模式·线程池·线程安全·死锁
desssq1 小时前
ubuntu 18.04 泰山派编译报错
linux·运维·ubuntu
Lzc7741 小时前
Linux的多线程
linux·linux的多线程
清风笑烟语1 小时前
Ubuntu 24.04 搭建k8s 1.33.4
linux·ubuntu·kubernetes
Dovis(誓平步青云)2 小时前
《Linux 基础指令实战:新手入门的命令行操作核心教程(第一篇)》
linux·运维·服务器
好名字更能让你们记住我2 小时前
MYSQL数据库初阶 之 MYSQL用户管理
linux·数据库·sql·mysql·adb·数据库开发·数据库架构