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

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Linux下,通常可以使用驱动程序包(如Intel的iwlwifi-firmware和Broadcom的wl)来安装网设备的驱动程序。另外,也可以使用发行版提供的更新机制(如Ubuntu的apt-get)来自动安装驱动程序。 ### 回答2: 在Linux操作系统下,网设备驱动程序是连接计算机和网络之间的关键组件,它负责控制和管理网设备的各种功能和操作。 在Linux中,网设备驱动程序是作为内核模块加载的。当系统启动时,内核会根据硬件检测到的网设备信息加载相应的驱动程序。这些驱动程序将与内核进行交互,以提供网络通信能力。 网设备驱动程序包含了相应网设备的底层控制逻辑和操作指令。它通过与内核交互,将上层网络协议栈的请求转换为底层网设备可以理解和处理的操作。这意味着网设备驱动程序负责处理包括数据发送、接收、处理和中断等操作,使得网络通信能够在硬件层面得以实现。 在Linux系统中,网设备驱动程序负责管理和配置网设备的属性和参数。用户可以通过不同的工具和命令来进行网设备的管理,如ifconfig、ethtool等。这些工具可以帮助用户查看和设置网设备的IP地址、子网掩码、数据帧大小等属性,以满足用户的网络需求。 此外,通过更新和升级网设备驱动程序,用户可以得到更好的性能和更好的兼容性。开源的Linux系统为用户提供了众多网设备驱动程序的选择,以满足不同硬件设备的需求。 综上所述,Linux下的网设备驱动程序承担着控制和管理网设备的重要角色,是实现网络通信的关键组件。通过加载适当的驱动程序,用户可以使用各种网设备并享受网络通信带来的便利。 ### 回答3: 在Linux系统中,网设备驱动程序负责管理和控制计算机上的网络接口。它们允许操作系统与网络硬件进行通信,并实现网络数据的传输。 网设备驱动程序通常由硬件制造商开发,以确保其与特定的网设备兼容。这些驱动程序编写成模块形式,可以动态地加载到内核中,或者作为静态链接编译到内核中。 在加载驱动程序时,操作系统通过设备树(如果使用的是现代的设备模型)或基于PCI系统的ioctl调用与网设备进行通信。驱动程序初始化网设备,设置接口参数,例如MAC地址,MTU等。此外,驱动程序还为设备提供一组网络协议参数,如IP地址、子网掩码和默认网关等。 一旦网设备驱动程序加载成功,操作系统便可以通过网络协议栈来发送和接收数据包。驱动程序负责处理硬件中断,收集和发送数据以及管理网络设备的状态。 在Linux中,常见的网设备驱动程序是以太网驱动程序。这些驱动程序包括广泛的硬件支持,从常见的千兆以太网控制器到无线网设备。 总之,Linux下的网设备驱动程序是允许操作系统与网络硬件进行通信,并实现网络数据传输的关键组件。它们负责初始化和管理网设备,处理硬件中断以及提供网络协议参数。这些驱动程序在操作系统启动时加载,以确保计算机可以连接到网络并进行通信。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值