linux下lame&alsa进行音频流操作(四)alsa+lame将音频流转为MP3

19 篇文章 2 订阅
11 篇文章 1 订阅

1.linux下使用alsa录音成pcm文件再使用lame转码为MP3

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <alsa/asoundlib.h>
#include <signal.h>
#include <lame/lame.h>


/*PCM文件转码成mp3文件*/
void ConvertPCM2MP3WithPath(const char *inputPath, const char *outputPath)
{
    size_t readSize, writeSize;

    /*打开pcm文件以及mp3文件*/
    FILE *pcmFile = fopen(inputPath, "rb");
    if (!pcmFile)
    {
        fprintf(stderr, "could not open %s\n", inputPath);
        return;
    }
    FILE *mp3File = fopen(outputPath, "wb");
    if (!mp3File)
    {
        fprintf(stderr, "could not open %s\n", outputPath);
        return;
    }

    const int PCM_BUFF_SIZE = 8192;
    const int MP3_BUFF_SIZE = 8192;

    short int pcm_buffer[PCM_BUFF_SIZE * 2];
    unsigned char mp3_buffer[MP3_BUFF_SIZE];

    lame_t lame = lame_init();
    lame_set_in_samplerate(lame, 44100);
    lame_set_VBR(lame, vbr_default);
    lame_init_params(lame);

    do
    {

        readSize = fread(pcm_buffer, 2 * sizeof(short int), PCM_BUFF_SIZE, pcmFile);

        printf("MP3::::::::::::: readSize: %ld \n", readSize);
        if (readSize == 0)
        {
            writeSize = lame_encode_flush(lame, mp3_buffer, MP3_BUFF_SIZE);
        }
        else
        {
            writeSize = lame_encode_buffer_interleaved(lame, pcm_buffer, (int)readSize, mp3_buffer, MP3_BUFF_SIZE);
        }

        fwrite(mp3_buffer, writeSize, 1, mp3File);

    } while (readSize != 0);

    lame_close(lame);
    fclose(mp3File);
    fclose(pcmFile);
}

static int recording;
/*CTL+C 取消录音*/
void stop_recording(int param)
{
    recording = 0;
}

/*开始录音*/
int StartRecode(const char *PcmFile)
{
    FILE *pFile;
    pFile = fopen(PcmFile, "wb");
    if (pFile == NULL)
    {
        printf("open Pcmdfile err!\n");
        return -1;
    }

    int rc;
    int size;
    snd_pcm_t *handle;
    snd_pcm_hw_params_t *params;
    unsigned int val;
    int dir;
    snd_pcm_uframes_t frames;
    char *buffer;

    /*打开PCM capture捕捉设备*/
    rc = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);
    if (rc < 0)
    {
        printf("can't open pcm devecie\n");
        exit(1);
    }

    /*分配一个硬件参数结构体*/
    snd_pcm_hw_params_alloca(&params);

    /*使用默认参数*/
    snd_pcm_hw_params_any(handle, params);

    /*Interleaved mode*/
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);

    /*设置16小端采样精度*/
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);

    /*双通道*/
    snd_pcm_hw_params_set_channels(handle, params, 2);

    /*采样率44100 CD级别音质*/
    val = 44100;
    snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);

    /*一个周期32帧*/
    frames = 32;
    snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);

    /*参数生效*/
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0)
    {
        printf("can't set hw params\n");
        exit(0);
    }

    /*得到一个周期的数据大小*/
    snd_pcm_hw_params_get_period_size(params, &frames, &dir);

    /* 16位采样精度 所以要*4*/
    size = frames * 4;
    buffer = (char *)malloc(size);
    if (buffer == NULL)
    {
        printf("malloc buffer size err!\n");
        return -2;
    }

    recording = 1;
    while (recording)
    {
        /*捕捉数据*/
        rc = snd_pcm_readi(handle, buffer, frames);
        if (rc == -EPIPE)
        {
            printf("over run occured\n");
            snd_pcm_prepare(handle);
        }
        else if (rc < 0)
        {
            printf("err from read!\n");
        }
        else if (rc != (int)frames)
        {
            printf("short read frames\n");
        }

        rc = fwrite(buffer, sizeof(char), size, pFile);
        if (rc != size)
        {
            printf("short write %d bytes\n", rc);
        }

        if (signal(SIGINT, stop_recording) == SIG_ERR)
        {
            printf("signal failed\n");
        }
    }
    /*关闭文件句柄*/
    snd_pcm_drain(handle);
    snd_pcm_close(handle);
    free(buffer);
    fclose(pFile);
}

int main(int argc, char *argv[])
{
    StartRecode("test.pcm");

    ConvertPCM2MP3WithPath("test.pcm", "Goal.mp3");

    const char *cmd = "rm -f test.pcm";
    system(cmd);

    return 0;
}

编译成可执行文件
gcc RecodePcm2Mp3.c -lasound -lmp3lame

2.linux下使用alsa收集音频流使用lame直接保存为MP3

代码1:

/*=============================================================================  
#     FileName: pcm_encoder_mp3.c  
#         Desc: use lame encode pcm data to mp3 format, the pcm data 
#				read from alsa  
#       Author: licaibiao  
#   LastChange: 2017-03-27   
=============================================================================*/ 
#define ALSA_PCM_NEW_HW_PARAMS_API
#include <alsa/asoundlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <lame/lame.h>
#define INBUFSIZE 128
#define MP3BUFSIZE (int) (1.25 * INBUFSIZE) + 7200
 
lame_global_flags	*gfp;
short				*input_buffer;
char 				*mp3_buffer;
char 				*outPath = "out.mp3";
FILE				*infp;
FILE				*outfp;
 
snd_pcm_hw_params_t *params;
snd_pcm_uframes_t   frames;
snd_pcm_t 			*handle;
int 				size;
short 				*alsa_buffer;
 
void lame_init_set(void)
{
	int ret_code;
    gfp = lame_init();
    if (gfp == NULL) 
    {
          printf("lame_init failed/n");
    }
 
    ret_code = lame_init_params(gfp);
    if (ret_code < 0)
    {
         printf("lame_init_params returned %d/n",ret_code);
    }
    outfp = fopen(outPath, "wb");	
}
 
void lame_alloc_buffer(void)
{
	input_buffer = (short*)malloc(INBUFSIZE*2);
    mp3_buffer = (char*)malloc(MP3BUFSIZE);	
}
 
void lame_release(void)
{
    free(mp3_buffer);
    free(input_buffer);
    fclose(outfp);
    lame_close(gfp);
}
 
void alsa_init(void){
	unsigned int 		val;
	int dir;
	int ret;
 
	ret = snd_pcm_open(&handle, "default", SND_PCM_STREAM_CAPTURE, 0);
	if (ret < 0) {
    	fprintf(stderr, "unable to open pcm device: %s\n", snd_strerror(ret));
   		 exit(1);
	}
 
	snd_pcm_hw_params_alloca(¶ms);
	snd_pcm_hw_params_any(handle, params);
	snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
	snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
	snd_pcm_hw_params_set_channels(handle, params, 2);
	val = 44100;
	snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);
	frames = 32;
	snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir);
	ret = snd_pcm_hw_params(handle, params);
	if (ret < 0) {
    	fprintf(stderr,"unable to set hw parameters: %s\n", snd_strerror(ret));
    	exit(1);
	}
}
 
void alsa_alloc_buffer(void){
	int dir;
 
	snd_pcm_hw_params_get_period_size(params, &frames, &dir);
	size = frames * 4; 
	alsa_buffer = (short *) malloc(size);
	
}
 
void alsa_release(void){
	snd_pcm_drain(handle);
	snd_pcm_close(handle);
	free(alsa_buffer);
}
void lame_encode(void) 
{
	int input_samples;
	int mp3_bytes;
	int status = 0;
	int ret = 0;
	int loop = 10000;
 
	while(loop--){
		ret = snd_pcm_readi(handle, alsa_buffer, frames);
		if (ret == -EPIPE){
			fprintf(stderr, "overrun occurred\n");
			snd_pcm_prepare(handle);
		}else if(ret == -EBADFD){
			printf("PCM is not in the right state \n");
		}
		else if(ret == -ESTRPIPE){
			printf("stream is suspended and waiting for an application recovery \n");
		}
		 else if (ret < 0){
			fprintf(stderr, "error from read: %s\n",snd_strerror(ret));
		}
		 else if (ret != (int)frames){
			 fprintf(stderr, "short read, read %d frames\n", ret);
		}
		else if (ret == 0){
			printf(" pcm read 0 frame deta \n ");
		}
 
	    memcpy(input_buffer, alsa_buffer, size);
		mp3_bytes = lame_encode_buffer_interleaved(gfp, input_buffer, size/4, mp3_buffer, MP3BUFSIZE);
		if (mp3_bytes < 0) 
		{
			  printf("lame_encode_buffer_interleaved returned %d \n", mp3_bytes);
		} 
		else if(mp3_bytes > 0) 
		{
			 fwrite(mp3_buffer, 1, mp3_bytes, outfp);
		}
	
	}
 
	mp3_bytes = lame_encode_flush(gfp, mp3_buffer, sizeof(mp3_buffer));
	if (mp3_bytes > 0) 
	{
		  printf("writing %d mp3 bytes\n", mp3_bytes);
		  fwrite(mp3_buffer, 1, mp3_bytes, outfp);
	}
}
 
int main(int argc, char** argv)
{
	lame_init_set();
	lame_alloc_buffer();
	alsa_init();
	alsa_alloc_buffer();
	lame_encode();
	lame_release();
	alsa_release();
}

代码2:
https://github.com/RichardoMrMu/alsa_lame_pcm_2_mp3?organization=RichardoMrMu&organization=RichardoMrMu

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值