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

相关推荐
Abladol-aj1 小时前
并发和并行的基础知识
java·linux·windows
JunLan~5 小时前
Rocky Linux 系统安装/部署 Docker
linux·docker·容器
方竞6 小时前
Linux空口抓包方法
linux·空口抓包
dccose7 小时前
vue3 uniapp 扫普通链接或二维码打开小程序并获取携带参数
小程序·uni-app
海岛日记7 小时前
centos一键卸载docker脚本
linux·docker·centos
AttackingLin8 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python
学Linux的语莫9 小时前
Ansible使用简介和基础使用
linux·运维·服务器·nginx·云计算·ansible
踏雪Vernon9 小时前
[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式
linux·docker·容器·harmonyos