继上篇:Android : alsa-lib 移植 ,这篇随笔实现一个demo基于移植好的alsa库在Android平台上播放wav文件:

一、利用ffmeg将一个mp3文件转换成wav文件

(1)ubuntu安装ffmeg工具:

sudo add-apt-repository ppa:djcj/hybrid

sudo apt-get update

sudo apt-get install ffmpeg

(2)mp3转wav:

   ffmpeg -i duandian.mp3 -f wav duandian.wav

二、demo代码:

/*
* This small demo sends a wave to your speakers.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <errno.h>
#include <getopt.h>
#include "../include/asoundlib.h"
#include <sys/time.h>
#include <math.h> static char *device = "hw:0,0"; /* playback device */
int blockMode = ; /* block mode */ /*
* RIFF WAVE file struct.
* For details see WAVE file format documentation
* (for example at http://www.wotsit.org).
*/
struct WAV_HEADER_S
{
char riffType[]; //4byte,资源交换文件标志:RIFF
unsigned int riffSize; //4byte,从下个地址到文件结尾的总字节数
char waveType[]; //4byte,wav文件标志:WAVE
char formatType[]; //4byte,波形文件标志:FMT(最后一位空格符)
unsigned int formatSize; //4byte,音频属性(compressionCode,numChannels,sampleRate,bytesPerSecond,blockAlign,bitsPerSample)所占字节数
unsigned short compressionCode;//2byte,编码格式种类(1-线性pcm-WAVE_FORMAT_PCM,WAVEFORMAT_ADPCM)
unsigned short numChannels; //2byte,通道数
unsigned int sampleRate; //4byte,采样率
unsigned int bytesPerSecond; //4byte,传输速率
unsigned short blockAlign; //2byte,数据块的对齐,即DATA数据块长度
unsigned short bitsPerSample; //2byte,采样精度-PCM位宽
char dataType[]; //4byte,数据标志:data
unsigned int dataSize; //4byte,从下个地址到文件结尾的总字节数,即除了wav header以外的pcm data length
} wav_header; /*
* Underrun and suspend recovery
*/
static int xrun_recovery(snd_pcm_t *handle, int err)
{
int wait_cnt=;
if (err == -EPIPE) { /* under-run */
//重新准备设备进行读写
err = snd_pcm_prepare(handle);
if (err < )
printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(err));
else
printf("underrun occurred\n");
return ;
} else if (err == -ESTRPIPE) {
while ((err = snd_pcm_resume(handle)) == -EAGAIN){
sleep(); /* wait until the suspend flag is released */
wait_cnt++;
if(wait_cnt >= ){
printf("suspend flag released fail after retry %d times!\n", wait_cnt);
break;
}
} if (err < ) {
err = snd_pcm_prepare(handle);
if (err < )
printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(err));
}
return ;
}
return err;
} 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=;
snd_pcm_uframes_t frames;
char *buffer;
int channels=wav_header.numChannels;
int frequency=wav_header.sampleRate;
int bit=wav_header.bitsPerSample;
int datablock=wav_header.blockAlign; rc=snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, blockMode ? : SND_PCM_NONBLOCK);
if(rc<)
{
perror("\open PCM device failed:");
exit();
} snd_pcm_hw_params_alloca(&params); //分配params结构体
if(rc<)
{
perror("\snd_pcm_hw_params_alloca:");
exit();
} rc=snd_pcm_hw_params_any(handle, params);//初始化params
if(rc<)
{
perror("\snd_pcm_hw_params_any:");
exit();
} rc=snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //初始化访问权限
if(rc<)
{
perror("\sed_pcm_hw_set_access:");
exit();
} //采样位数
switch(bit/) {
case :snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_U8);
break ;
case :snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);
break ;
case :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<)
{
perror("\nsnd_pcm_hw_params_set_channels:");
exit();
} val = frequency;
rc=snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //设置>频率
if(rc<)
{
perror("\nsnd_pcm_hw_params_set_rate_near:");
exit();
} rc = snd_pcm_hw_params(handle, params);
if(rc<)
{
perror("\nsnd_pcm_hw_params: ");
exit();
} rc=snd_pcm_hw_params_get_period_size(params, &frames, &dir); /*获取周期长度*/
if(rc<)
{
perror("\nsnd_pcm_hw_params_get_period_size:");
exit();
} size = frames * datablock; /*4 : 代表数据块长度*/ buffer =(char*)malloc(size);
fseek(fp,sizeof(wav_header),SEEK_SET); //定位歌曲到数据区 while ()
{
memset(buffer,,sizeof(buffer));
ret = fread(buffer, , size, fp);
if(ret == )
{
printf("music write done!\n");
break;
} else if (ret != size) {
printf("music read out of size !\n");
} /* use poll to wait for next event */
write_data: if(snd_pcm_wait(handle, )){
ret = snd_pcm_writei(handle,buffer,frames); // 写音频数据到PCM设备
if(ret == -EAGAIN){
printf("write EAGAIN\n");
goto write_data;
}
else if(ret < ){
if (xrun_recovery(handle, ret) < ) {
printf("Write error: %s\n", snd_strerror(ret));
break;
}
}
}
} snd_pcm_drain(handle);
snd_pcm_close(handle);
free(buffer);
return ;
} int pcm_main(int argc,char *argv[])
{ if(argc!=)
{
printf("Usage : ./nanosic_apps file_name.wav\n");
exit();
} int nread;
FILE *fp;
fp=fopen(argv[],"rb");
if(fp==NULL)
{
perror("open file failed:\n");
exit();
} nread=fread(&wav_header,,sizeof(wav_header),fp);
/*example:
Read wav_header size = 44
RIFF flag = RIFF?à?WAVEfmt
riffSize = 47308956
waveType = WAVEfmt
formatType = fmt
formatSize = 16
compressionCode = 1
channels = 2
Sample rate = 44100
bytesPerSecond = 176400
blockAlign = 4
bitsPerSample = 16
data = LISTp
dataSize = 112
*/
printf("Read wav_header size = %d\n",nread);
printf("RIFF flag = %s\n",wav_header.riffType);
printf("riffSize = %d\n",wav_header.riffSize);
printf("waveType = %s\n",wav_header.waveType);
printf("formatType = %s\n",wav_header.formatType);
printf("formatSize = %d\n",wav_header.formatSize);
printf("compressionCode = %d\n",wav_header.compressionCode);
printf("channels = %d\n",wav_header.numChannels);
printf("Sample rate = %d\n",wav_header.sampleRate);
printf("bytesPerSecond = %d\n",wav_header.bytesPerSecond);
printf("blockAlign = %d\n",wav_header.blockAlign);
printf("bitsPerSample = %d\n",wav_header.bitsPerSample);
printf("data = %s\n",wav_header.dataType);
printf("dataSize = %d\n",wav_header.dataSize); set_pcm_play(fp); //向PCM设备写入数据 return ;
}

Android : 基于alsa库的音乐播放的更多相关文章

  1. 基于jQuery仿QQ音乐播放器网页版代码

    基于jQuery仿QQ音乐播放器网页版代码是一款黑色样式风格的网页QQ音乐播放器样式代码.效果图如下: 在线预览   源码下载 实现的代码. html代码: <div class="m ...

  2. iOS之基于FreeStreamer的简单音乐播放器(模仿QQ音乐)

    代码地址如下:http://www.demodashi.com/demo/11944.html 天道酬勤 前言 作为一名iOS开发者,每当使用APP的时候,总难免会情不自禁的去想想,这个怎么做的?该怎 ...

  3. Android应用--简、美音乐播放器增加音量控制

    Android应用--简.美音乐播放器增加音量控制 2013年6月26日简.美音乐播放器继续完善中.. 题外话:上一篇博客是在6月11号发的,那篇博客似乎有点问题,可能是因为代码结构有点乱的原因,很难 ...

  4. Android应用--简、美音乐播放器获取专辑图片(自定义列表适配器)

    Android应用--简.美音乐播放器获取专辑图片(自定义列表适配器) 2013年7月3日简.美音乐播放器开发 第二阶段已增加功能: 1.歌词滚动显示 2.来电监听 3.音量控制 4.左右滑动切换歌词 ...

  5. 基于Qt的开源音乐播放器(CZPlayer)

    CZPlayer CZPlayer是基于Qt开发的一款功能强大的音乐播放器,该播放器的论坛地址请点击here,目前CZPlayer已经是第四个版本了,历史版本也分别在我的github上, github ...

  6. android快捷简单的实现音乐播放器

    自己做了一个相对完整的音乐播放器,现在把播放模块提取出来,分享给大家.音乐播放器基本功能都实现了的,可能有些BUG,希望谅解. 播放器功能如下: 1.暂停,播放 2.拖动条实现,快进,快退 3.歌词同 ...

  7. Android开发实战之简单音乐播放器

    最近开始学习音频相关.所以,很想自己做一个音乐播放器,于是,花了一天学习,将播放器的基本功能实现了出来.我觉得学习知识点还是蛮多的,所以写篇博客总结一下关于一个音乐播放器实现的逻辑.希望这篇博文对你的 ...

  8. Swift 3 :基于 AVAudioPlayer 的简单音乐播放器

    2017.05.22 17:46* 字数 1585 阅读 5095评论 0喜欢 8赞赏 2 https://www.jianshu.com/p/4d5c257428a1 学习ios以来差不多接近两个月 ...

  9. 基于JavaFX实现的音乐播放器

    前言 这个是本科四年的毕业设计,我个人自命题的一个音乐播放器的设计与实现,其实也存在一些功能还没完全开发完成,但粗略的答辩也就过去了,还让我拿了个优秀,好开心.界面UI是参考网易云UWP版本的,即使这 ...

随机推荐

  1. Python3之JSON数据解析实例:新闻头条 --Python3

    一.接口相关 数据服务商:聚合数据(https://www.juhe.cn/) API部分文档: 完整API文档下载:https://files.cnblogs.com/files/qikeyishu ...

  2. JS获取系统时间--JavaScript基础

    1.网页中实时显示当前时间 <!DOCTYPE html><html lang="en"><head> <meta charset=&qu ...

  3. HDOJ-1806 ( Frequent values ) 线段树区间合并

    http://acm.hdu.edu.cn/showproblem.php?pid=1806 线段树维护区间出现频率最高的出现次数.为了维护上者,需要维护线段前后缀的出现次数,当和其他线段在端点处的字 ...

  4. php 商场收银收费系统,使用的策略模式

    <?php//策略模式就是你有很多的方法,选择一种适合自己的,// 单例模式就是只有一个实例对象,不需要每个文件都要加载,比如连接数据库,// 工厂模式就是 //策略模式 优惠系统.工资计算系统 ...

  5. python记录_day018 md5加密

    MD5 用法: import hashlib obj = hashlib.md5(加盐) obj.update(明文的bytes) obj.hexdigest() 获取密文 示例: import ha ...

  6. hdu5608杜教筛

    题意:给定函数\(f(x)\),有\(n^2-3*n+2=\sum_{d|n}f(d)\),求\(\sum_{i=1}^nf(i)\) 题解:很显然的杜教筛,假设\(g(n)=n^2-3*n+2\), ...

  7. php 字符编码转换

    <?php/** * Created by PhpStorm. * User: yxp * Date: 2016/11/8 * Time: 16:47 */ /** * 将非GBK字符集的编码转 ...

  8. hdu-6341-搜索

    Problem J. Let Sudoku Rotate Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K ...

  9. sharding-jdbc读写分离原理解读

    原帖地址:https://blog.csdn.net/yanyan19880509/article/details/78170233 前言 很多时候,为了应付DB的高并发读写,我们会采用读写分离技术. ...

  10. Oracle Cursor用法总结

    cursor分为三种,一是直接声明为cursor变量,二是首先声明类型再声明变量,三是声明为sys_refcursor. (1)直接声明 declare cursor emp_cur  is sele ...