继上篇: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. 雷林鹏分享:jQuery EasyUI 插件

    jQuery EasyUI 插件 jQuery EasyUI 提供了用于创建跨浏览器网页的完整的组件集合,包括功能强大的 datagrid(数据网格).treegrid(树形表格). panel(面板 ...

  2. 大数据量 与 UI交互时的处理 总结与心得

    [以下均在主线程中操作时]1.UI直接操作,数据量较大时,直接使用UI会非常慢2.数据驱动操作,数据量较大时,数据与UI的交互效率相比“1”提升明显 总结:但以上这两种操作  都会“较长时间”占用主线 ...

  3. CSS3实现烟花特效 --web前端

    烟花特效,比较简单,直接贴代码了…… <!DOCTYPE html><html lang="en"><head> <meta charse ...

  4. Android+Servlet+MySql+JSON实现简单的数据查询操作--C/S架构

    本例简单地实现Android客户端与服务器端交互,主要是通过客户端输入内容(学号)提交到服务器端,服务器端与数据库交互去查询相应信息(姓名).根据这个做个完整的安卓登录是没问题的.本例数据库服务器都采 ...

  5. Aliyun cdn访问日志下载

    1.日志下载代码(cdn.py)(请在Linux系统下运行) #!/usr/bin/python2.7 # -*- coding:utf-8 -*- import sys,os,gzip,json,r ...

  6. G711编解码

    http://blog.csdn.net/rightorwrong/article/details/4209467 搞语音对讲几天了,播放时声音干扰太大了.拖得时间久有两个原因: 1.每次采样的位数这 ...

  7. Hadoop/HBase Capacity Planning

    http://blog.cloudera.com/blog/2010/08/hadoophbase-capacity-planning/

  8. unitest 测试集 实例

    -->baidy.py #coding=utf-8from selenium import webdriverfrom selenium.webdriver.common.by import B ...

  9. bzoj2555: SubString sam+lct

    题意:懒得写背景了,给你一个字符串init,要求你支持两个操作 (1):在当前字符串的后面插入一个字符串 (2):询问字符串s在当前字符串中出现了几次?(作为连续子串) 你必须在线支持这些操作. 题解 ...

  10. 【微信公众号开发】【10】JSJDK相关

    前言: 1,优点:官方提供的,会调用后还算使用方便,不用费劲了解各个原生组件 缺点:使用上有限制(如:上传文件有大小限制),很容易踩坑,部分安卓手机及电脑端不支持pjax 总结:上手容易,坑很多 2, ...