基于ALSA lib录音接口
来源:互联网 发布:unity3d游戏打不开 编辑:程序博客网 时间:2024/06/10 23:40
接口文件 record_interface.h
/** * @file record_interface.h * @brief For the operation of record API */#ifndef __record_INTERFACE_HEAD__#define __record_INTERFACE_HEAD__#include <stdio.h>#include <malloc.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <getopt.h>#include <fcntl.h>#include <ctype.h>#include <errno.h>#include <limits.h>#include <time.h>#include <locale.h>#include <sys/unistd.h>#include <sys/stat.h>#include <sys/types.h>#include "alsa/asoundlib.h"#include <assert.h>typedef unsigned char uint8_t;typedef unsigned short uint16_t;typedef unsigned int uint32_t;typedef struct { /** * @brief Alsa handle. */ snd_pcm_t *handle; /** * @brief Alsa log Output redirection. */ snd_output_t *log; /** * @brief Alsa internal audio cache buffer size. */ snd_pcm_uframes_t buffer_size; /** * @brief Data format. */ snd_pcm_format_t format; /** * @brief The number of channels. */ uint16_t channels; /** * @brief The number of bit per sample point. */ size_t bits_per_sample; /** * @brief The number of bit per frame. */ size_t bits_per_frame; /** * @brief The amount of frame required to record. */ snd_pcm_uframes_t chunk_size; /** * @brief The number of bytes required to be recorded is matched with the * chunk_size. */ size_t chunk_bytes; /** * @brief Point to the recording data buffer, the size is chunk_bytes bytes, * have chunk_size frame. */ uint8_t *data_buf;} record_handle_t;typedef struct { /* * Specifies data format. * SND_PCM_FORMAT_S16_LE; * SND_PCM_FORMAT_S8; * SND_PCM_FORMAT_UNKNOWN; * All references at sound/asound.h */ snd_pcm_format_t format; /** * @brief Specifies the number of channels. */ uint16_t channels; /** * @brief frequence of sample */ uint32_t sample_rate;} record_params_t;/** * @brief Get the handle for the recording. * * @param record_params Recording parameters. * * @return Record handle on success otherwise NULL is returned. */record_handle_t *mozart_get_record_handle(record_params_t record_params);/** * @brief Get the recording data, the size is chunk_bytes bytes. * * @param record_handle * * @return Return a pointer to data on success otherwise NULL is returned. */uint8_t *mozart_record_get_data(record_handle_t * record_handle);/** * @brief Release record handle after call mozart_get_record_handle. * * @param record_handle */void mozart_release_record_handle(record_handle_t * record_handle);#endif /* __record_INTERFACE_HEAD__ */
实现文件 record.c
/** * @file record.c * @brief For the operation of record API */#include "record_interface.h"#define DEBUG(x,y...) {printf("[ %s : %s : %d] ",__FILE__, __func__, __LINE__); printf(x,##y); printf("\n");}#define ERROR(x,y...) {printf("[ %s : %s : %d] ",__FILE__, __func__, __LINE__); printf(x,##y); printf("\n");}static int record_set_params(record_handle_t * record_handle, record_params_t record_params){ snd_pcm_hw_params_t *hwparams; 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(record_handle->handle, hwparams) < 0) { ERROR("Error snd_pcm_hw_params_any"); goto ERR_SET_PARAMS; } if (snd_pcm_hw_params_set_access(record_handle->handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED) < 0) { ERROR("Error snd_pcm_hw_params_set_access"); goto ERR_SET_PARAMS; } if (snd_pcm_hw_params_set_format(record_handle->handle, hwparams, record_params.format) < 0) { ERROR("Error snd_pcm_hw_params_set_format"); goto ERR_SET_PARAMS; } record_handle->format = record_params.format; /* Set number of channels */ if (snd_pcm_hw_params_set_channels(record_handle->handle, hwparams, record_params.channels) < 0) { ERROR("Error snd_pcm_hw_params_set_channels"); goto ERR_SET_PARAMS; } record_handle->channels = record_params.channels; /* Set sample rate. If the exact rate is not supported */ /* by the hardware, use nearest possible rate. */ exact_rate = record_params.sample_rate; if (snd_pcm_hw_params_set_rate_near(record_handle->handle, hwparams, &exact_rate, 0) < 0) { ERROR("Error snd_pcm_hw_params_set_rate_near"); goto ERR_SET_PARAMS; } if (record_params.sample_rate != exact_rate) { ERROR("The rate %d Hz is not supported by your hardware. ==> Using %d Hz instead.", record_params.sample_rate, exact_rate); } if (snd_pcm_hw_params_get_buffer_time_max(hwparams, &buffer_time, 0) < 0) { ERROR("Error snd_pcm_hw_params_get_buffer_time_max"); 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(record_handle->handle, hwparams, &buffer_time, 0) < 0) { ERROR("Error snd_pcm_hw_params_set_buffer_time_near"); goto ERR_SET_PARAMS; } if (snd_pcm_hw_params_set_period_time_near(record_handle->handle, hwparams, &period_time, 0) < 0) { ERROR("Error snd_pcm_hw_params_set_period_time_near"); goto ERR_SET_PARAMS; } /* Set hw params */ if (snd_pcm_hw_params(record_handle->handle, hwparams) < 0) { ERROR("Error snd_pcm_hw_params(handle, params)"); goto ERR_SET_PARAMS; } snd_pcm_hw_params_get_period_size(hwparams, &record_handle->chunk_size, 0); snd_pcm_hw_params_get_buffer_size(hwparams, &record_handle->buffer_size); if (record_handle->chunk_size == record_handle->buffer_size) { ERROR(("Can't use period equal to buffer size (%lu == %lu)"), record_handle->chunk_size, record_handle->buffer_size); goto ERR_SET_PARAMS; } //通过fomart获取每sample的bit数 record_handle->bits_per_sample = snd_pcm_format_physical_width(record_params.format); //把frame定义为一个sample的数据,包括每个channel record_handle->bits_per_frame = record_handle->bits_per_sample * record_params.channels; //计算录chunk_size个frame需要的byte数 record_handle->chunk_bytes = record_handle->chunk_size * record_handle->bits_per_frame / 8; //开辟录音buffer record_handle->data_buf = (uint8_t *)malloc(record_handle->chunk_bytes); if (!record_handle->data_buf) { ERROR("Error malloc: [data_buf]"); goto ERR_SET_PARAMS; } return 0;ERR_SET_PARAMS: return -1;}record_handle_t *mozart_get_record_handle(record_params_t record_params){ char *devicename = "default"; record_handle_t *record_handle; record_handle = (record_handle_t *)malloc(sizeof(record_handle_t)); memset(record_handle, 0x0, sizeof(record_handle_t)); if (snd_output_stdio_attach(&record_handle->log, stderr, 0) < 0) { ERROR("Error snd_output_stdio_attach"); free(record_handle); return NULL; } if (snd_pcm_open(&(record_handle->handle), devicename, SND_PCM_STREAM_CAPTURE, 0) < 0) { ERROR("Error snd_pcm_open [ %s]", devicename); free(record_handle); return NULL; } if (record_set_params(record_handle, record_params) < 0) { ERROR("Error set_snd_pcm_params"); free(record_handle); return NULL; } //snd_pcm_dump(record_handle->handle, record_handle->log); return record_handle;}static ssize_t read_pcm(record_handle_t *record_handle){ ssize_t r; size_t result = 0; size_t count = record_handle->chunk_size; uint8_t *data = record_handle->data_buf; while (count > 0) { //录count个frame到data中 r = snd_pcm_readi(record_handle->handle, data, count); if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) { snd_pcm_wait(record_handle->handle, 1000); } else if (r == -EPIPE) { snd_pcm_prepare(record_handle->handle); fprintf(stderr, "<<<<<<<<<<<<<<< Buffer Underrun >>>>>>>>>>>>>>>\n"); } else if (r == -ESTRPIPE) { fprintf(stderr, "<<<<<<<<<<<<<<< Need suspend >>>>>>>>>>>>>>>\n"); } else if (r < 0) { fprintf(stderr, "Error snd_pcm_readi: [%s]", snd_strerror(r)); return -1; } if (r > 0) { result += r; count -= r; data += r * record_handle->bits_per_frame / 8; } } return result;}uint8_t *mozart_record_get_data(record_handle_t * record_handle){ if (read_pcm(record_handle) != record_handle->chunk_size) return NULL; return record_handle->data_buf;}void mozart_release_record_handle(record_handle_t * record_handle){ snd_pcm_drain(record_handle->handle); free(record_handle->data_buf); snd_output_close(record_handle->log); snd_pcm_close(record_handle->handle);}
0 0
- 基于ALSA lib录音接口
- alsa-lib、tinyalsa以及基于alsa的用户空间编程
- 基于s3c2440的alsa-lib及alsa-utils成功移植
- 基于s3c2440的alsa-lib及alsa-utils成功移植
- 基于ALSA的WAV播放和录音程序
- 基于ALSA的WAV播放和录音程序
- 基于ALSA的WAV播放和录音程序
- 基于ALSA架构的声卡播放录音设置
- 基于ALSA的WAV播放和录音程序
- 基于ALSA的WAV播放和录音程序
- 基于ALSA的WAV播放和录音程序
- 基于ALSA的WAV播放和录音程序
- 基于ALSA的WAV播放和录音程序
- 基于ALSA的WAV播放和录音程序
- alsa lib
- 基于Alsa lib进行音量调节以及静音操作
- Alsa框架录音程序
- ALSA接口
- css3 字内容变色 临内容变色
- android 图片放大缩小的边界简单的限制处理
- Java String和Date的转换
- Android中Application类用法
- 互联网精准广告定向技术
- 基于ALSA lib录音接口
- DelphiXE8中获取APK的签名信息
- 网页图片左右滚动特效实例
- IntentFilter
- 题目1387:斐波那契数列
- 重庆治疗静脉曲张费用
- MFC有的函数前面加::是什么意思
- 集合框架
- THIS_MODULE