也说alsa音乐播放(mp3文件从零开始)

首先也是最重要的是:我说大话了,本文也就是一个思路而已,如果你是音乐播放小白也想弄明白原理可以往下看,否则,return -1;

现有的音乐格式千差万别,于是就有了ffmpeg话说这个框架真是够牛逼,音频视频转码都不在话下,我是个死脑筋,遇到不懂的老是想弄明白,对于音乐播放感觉是一头雾水,经过几天的研究以后大致想明白了,对一个mp3文件要播放出来需要经过几个步骤:

1.转码,其实也就是提取文件中有用的音频信息

2.经过第一步得到的wav波形文件

3.调用声卡来播放wav文件,对于linux 3.0以后的内核一般为alsa驱动,windows对wav也是天然支持的

关于转码可以见大婶写的转码系列教程http://lfp001.iteye.com/blog/739585

转码命令:

ffmepg -i 1.mp3 -f wav 1.wav

编译: gcc -o alsa alsa.c -lasound

播放命令

./alsa 1.wav

//alsa.c 编写者未知,纯属引用
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include <alsa/asoundlib.h>

struct WAV_HEADER
{
    char rld[4];    //riff 标志符号
    int rLen;
    char wld[4];    //格式类型(wave)
    char fld[4];    //"fmt"

    int fLen;   //sizeof(wave format matex)

    short wFormatTag;   //编码格式
    short wChannels;    //声道数
    int   nSamplesPersec ;  //采样频率
    int   nAvgBitsPerSample;//WAVE文件采样大小
    short  wBlockAlign; //块对齐
    short wBitsPerSample;   //WAVE文件采样大小

    char dld[4];        //”data“
    int wSampleLength;  //音频数据的大小

} wav_header;

int set_pcm_play(FILE *fp);

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

    if(argc!=2)
    {
        printf("Usage:wav-player+wav file name\n");
        exit(1);
    }

    int nread;
    FILE *fp;
    fp=fopen(argv[1],"rb");
    if(fp==NULL)
    {
        perror("open file failed:\n");
        exit(1);
    }

    nread=fread(&wav_header,1,sizeof(wav_header),fp);
    printf("nread=%d\n",nread);

    //printf("RIFF 标志%s\n",wav_header.rld);
    printf("文件大小rLen:%d\n",wav_header.rLen);
    //printf("wld=%s\n",wav_header.wld);
    //printf("fld=%s\n",wav_header.fld);

   // printf("fLen=%d\n",wav_header.fLen);

    //printf("wFormatTag=%d\n",wav_header.wFormatTag);
    printf("声道数:%d\n",wav_header.wChannels);
    printf("采样频率:%d\n",wav_header.nSamplesPersec);
    //printf("nAvgBitsPerSample=%d\n",wav_header.nAvgBitsPerSample);
    //printf("wBlockAlign=%d\n",wav_header.wBlockAlign);
    printf("采样的位数:%d\n",wav_header.wBitsPerSample);

   // printf("data=%s\n",wav_header.dld);
    printf("wSampleLength=%d\n",wav_header.wSampleLength);

    set_pcm_play(fp);
    return 0;
}

int set_pcm_play(FILE *fp)
{
        int    rc;
        int    ret;
        int    size;
        snd_pcm_t*       handle;        //PCI设备句柄
        snd_pcm_hw_params_t*      params;//硬件信息和PCM流配置
        unsigned int       val;
        int                dir=0;
        snd_pcm_uframes_t  frames;
        char   *buffer;
        int channels=wav_header.wChannels;
        int frequency=wav_header.nSamplesPersec;
        int bit=wav_header.wBitsPerSample;
        int datablock=wav_header.wBlockAlign;
        unsigned char ch[100];  //用来存储wav文件的头信息

        rc=snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
        if(rc<0)
        {
                perror("\nopen PCM device failed:");
                exit(1);
        }

        snd_pcm_hw_params_alloca(¶ms); //分配params结构体
        if(rc<0)
        {
                perror("\nsnd_pcm_hw_params_alloca:");
                exit(1);
        }
         rc=snd_pcm_hw_params_any(handle, params);//初始化params
        if(rc<0)
        {
                perror("\nsnd_pcm_hw_params_any:");
                exit(1);
        }
        rc=snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);                                 //初始化访问权限
        if(rc<0)
        {
                perror("\nsed_pcm_hw_set_access:");
                exit(1);

        }

        //采样位数
        switch(bit/8)
        {
        case 1:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8);
                break ;
        case 2:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
                break ;
        case 3:snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S24_LE);
                break ;

        }
        rc=snd_pcm_hw_params_set_channels(handle, params, channels);  //设置声道,1表示单声>道,2表示立体声
        if(rc<0)
        {
                perror("\nsnd_pcm_hw_params_set_channels:");
                exit(1);
        }
        val = frequency;
        rc=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir);  //设置>频率
        if(rc<0)
        {
                perror("\nsnd_pcm_hw_params_set_rate_near:");
                exit(1);
        }

        rc = snd_pcm_hw_params(handle, params);
        if(rc<0)
        {
        perror("\nsnd_pcm_hw_params: ");
        exit(1);
        }

        rc=snd_pcm_hw_params_get_period_size(params, &frames, &dir);  /*获取周期长度*/
        if(rc<0)
        {
                perror("\nsnd_pcm_hw_params_get_period_size:");
                exit(1);
        }

        size = frames * datablock;   /*4 代表数据快长度*/

        buffer =(char*)malloc(size);
    fseek(fp,58,SEEK_SET);  //定位歌曲到数据区

    while (1)
        {
                memset(buffer,0,sizeof(buffer));
                ret = fread(buffer, 1, size, fp);
                if(ret == 0)
                {
                        printf("歌曲写入结束\n");
                        break;
                }
                 else if (ret != size)
                {
                 }
                // 写音频数据到PCM设备
        while(ret = snd_pcm_writei(handle, buffer, frames)<0)
           {
                 usleep(2000);
                 if (ret == -EPIPE)
                {
                  /* EPIPE means underrun */
                  fprintf(stderr, "underrun occurred\n");
                  //完成硬件参数设置,使设备准备好
                  snd_pcm_prepare(handle);
                 }
                 else if (ret < 0)
                 {
                          fprintf(stderr,
                      "error from writei: %s\n",
                      snd_strerror(ret));
                 }
            }

    }

        snd_pcm_drain(handle);
        snd_pcm_close(handle);
        free(buffer);
        return 0;
}
时间: 2024-10-27 07:20:12

也说alsa音乐播放(mp3文件从零开始)的相关文章

MCI播放mp3文件error:初始化mci时发生问题

今天使用MCI写一个音乐播放器雏形的时候,使用的是mp3文件,在打开第一个文件时候还没有问题,但是在换了一个mp3文件之后,发现打开文件失败了,使用mciGetErrorString函数得到其错误为:初始化mci时发生问题. 在百度上找了很多问题,都没有找到,在一个贴吧里看见有人说似乎只有网易云音乐的mp3文件打开会出现问题,别的都不会.抱着这个想法,又在qq音乐上下了一个mp3音乐文件,果然没有问题. 但是知其然不知其所以然,还是很迷惑.后来想到可以把这个中文错误翻译一下在bing或者Goog

xcode 中用AvAudioPlayer播放mp3文件

[playButton setEnabled:YES]; NSError *playerError; AVAudioPlayer *audioPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:[[[NSURL alloc] initFileURLWithPath:mp3FilePath] autorelease] error:&playerError]; self.player = audioPlayer; player.volume =

读取SD卡文件夹下的MP3文件和播放MP3文件

首先获取SD卡path路径下的所有的MP3文件,并将文件名和文件大小存入List数组(此代码定义在FileUtils类中): /** * 读取目录中的Mp3文件的名字和大小 */ public List<Mp3Info> getMp3Files(String path) { SDCardRoot = Environment.getExternalStorageDirectory() .getAbsolutePath(); //获取SD卡的路径名 List<Mp3Info> mp3I

java获取mp3的时长和播放mp3文件

所需包为jaudiotagger-2.2.6-SNAPSHOT.jar和jl1.0.1.jar. import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import org.jaudiotagger.audio.AudioFileIO; import org.jaudiotagger.audio.mp3.MP3AudioHeader; import org.jaudiota

UIwebview 文件的下载与保存,以及mp3文件的播放

http://blog.csdn.net/a6472953/article/details/7866033 [cpp] view plaincopy 这里只是说说异步 单线程下载与文件的保存 以下载一个mp3文件并保存为例: -(void)loading { //设置文件下载地址 NSString *urlString = [NSString stringWithFormat:@"http://zhangmenshiting2.baidu.com/data2/music/14893666/148

Unity3d:播放物理目录下的MP3文件

u3d里,是支持播放MP3文件的,但要放到资源里,不支持播放物理目录下的MP3文件.由于界面上无需显示,只是当作背景音乐来播放,所以想到调用c#的组件来解决此问题.主要代码都在附件中,根据需要加到自己的u3d程序里即可.贴士:此类问题容易造成局限性,只局限在u3d里面,u3d不支持了就判了死刑,而忘记真正的药是c#,u3d只是汤而已 源码下载 Unity3d:播放物理目录下的MP3文件,布布扣,bubuko.com

迷宫问题(输出路径)_友好界面_音乐播放_彩色字体

1 /* 2 8 6 3 1 1 1 1 1 1 1 1 4 1 0 0 1 0 0 1 1 5 1 1 0 0 0 0 0 1 6 1 0 0 1 0 1 0 1 7 1 0 0 0 0 0 0 1 8 1 1 1 1 1 1 1 1 9 */ 10 #include <iostream> //////////-static-libgcc 11 #include <iomanip> 12 #include <ctime> 13 #include <stack&g

pygame加载中文名mp3文件出现error

好一阵子没有写东西了,最近几天在做一个基于Python pygame的音乐播放器,本来想做完了,再来发篇文章的,可越做越深,框架大致出来了,考虑周期比较长,也可能是我个人问题,做得比较慢.下面来谈谈pygame.mixer.music.load()加载中文名的mp3文件问题. (发表时间2017-03-30 22:45:58 原创链接http://www.cnblogs.com/dearvee/p/6649055.html) #前言: 今天刚刚做了个音乐列表,但笔者发现在指定目录mp3文件名为中

使用LM386制作Arduino音乐播放器

在我们的项目中添加声音或音乐总是会使其看起来更酷一些,听上去更有吸引力.特别是如果您使用的是Arduino开发板,并且有很多空余的引脚,只需要添加一个SD卡模块和一个普通的扬声器即可轻松添加音效.在本文中,我将向您展示使用您的Arduino开发板来播放音乐以及添加音效是多么容易.感谢Arduino社区开发了一些库,可以使用快速而简便的方式实现..我们也在这里使用了LM386芯片进行放大和噪声消除. 需要的硬件: 1.  Arduino UNO开发板 2.  SD卡读卡器模块 3.  SD卡 4.