Android : 基于alsa库的音乐播放
继上篇: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(¶ms); //分配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库的音乐播放的更多相关文章
- 基于jQuery仿QQ音乐播放器网页版代码
基于jQuery仿QQ音乐播放器网页版代码是一款黑色样式风格的网页QQ音乐播放器样式代码.效果图如下: 在线预览 源码下载 实现的代码. html代码: <div class="m ...
- iOS之基于FreeStreamer的简单音乐播放器(模仿QQ音乐)
代码地址如下:http://www.demodashi.com/demo/11944.html 天道酬勤 前言 作为一名iOS开发者,每当使用APP的时候,总难免会情不自禁的去想想,这个怎么做的?该怎 ...
- Android应用--简、美音乐播放器增加音量控制
Android应用--简.美音乐播放器增加音量控制 2013年6月26日简.美音乐播放器继续完善中.. 题外话:上一篇博客是在6月11号发的,那篇博客似乎有点问题,可能是因为代码结构有点乱的原因,很难 ...
- Android应用--简、美音乐播放器获取专辑图片(自定义列表适配器)
Android应用--简.美音乐播放器获取专辑图片(自定义列表适配器) 2013年7月3日简.美音乐播放器开发 第二阶段已增加功能: 1.歌词滚动显示 2.来电监听 3.音量控制 4.左右滑动切换歌词 ...
- 基于Qt的开源音乐播放器(CZPlayer)
CZPlayer CZPlayer是基于Qt开发的一款功能强大的音乐播放器,该播放器的论坛地址请点击here,目前CZPlayer已经是第四个版本了,历史版本也分别在我的github上, github ...
- android快捷简单的实现音乐播放器
自己做了一个相对完整的音乐播放器,现在把播放模块提取出来,分享给大家.音乐播放器基本功能都实现了的,可能有些BUG,希望谅解. 播放器功能如下: 1.暂停,播放 2.拖动条实现,快进,快退 3.歌词同 ...
- Android开发实战之简单音乐播放器
最近开始学习音频相关.所以,很想自己做一个音乐播放器,于是,花了一天学习,将播放器的基本功能实现了出来.我觉得学习知识点还是蛮多的,所以写篇博客总结一下关于一个音乐播放器实现的逻辑.希望这篇博文对你的 ...
- Swift 3 :基于 AVAudioPlayer 的简单音乐播放器
2017.05.22 17:46* 字数 1585 阅读 5095评论 0喜欢 8赞赏 2 https://www.jianshu.com/p/4d5c257428a1 学习ios以来差不多接近两个月 ...
- 基于JavaFX实现的音乐播放器
前言 这个是本科四年的毕业设计,我个人自命题的一个音乐播放器的设计与实现,其实也存在一些功能还没完全开发完成,但粗略的答辩也就过去了,还让我拿了个优秀,好开心.界面UI是参考网易云UWP版本的,即使这 ...
随机推荐
- change color1
private void Form1_Load(object sender, EventArgs e) { string str = "server= ...
- WPF经典编程模式-MVVM示例讲解
https://www.cnblogs.com/lvdongjie/p/5515962.html
- python2.x编码问题实例
1,编码问题,主要是区分面向人类的字符串,面向计算机的字节序列 在python3中,字符串是str(默认即unicode),字节序列是bytes 在python2中,字符串是unicode,字节序列是 ...
- Watto and Mechanism CodeForces - 514C (字典树,哈希)
大意: 给定字符串集$S$, 每次询问给出字符串$a$, 求$S$中是否存在一个字符串恰好与$a$相差一个字符. 直接建字典树暴力复杂度是$O(n\sqrt{n})$, 也可以用set维护所有哈希值, ...
- JIT编译器技术理解
参考链接: https://blog.csdn.net/liaodehong/article/details/51605457 https://www.cnblogs.com/insistence/p ...
- bat语法需要注意的地方
if else 格式 if exist C:\Python27 ::空格 ( ::(与if在同一行 ...
- const constptr 和引用的盲点(未解决)
#include<iostream> //const 和 引用的值必须初始化 //等号左侧是const或者const和引用,右侧可以是数字,普通变量-等号左侧是const和指针,右侧必须是 ...
- 安装sql 2008步骤以及所遇到的问题
下载网址:http://www.xiazaiba.com/html/4610.html 安装步骤: 1. 在Windows7操作系统系,启动Microsoft SQL 2008安装程序后,系统兼容性 ...
- CSS3透明背景+渐变样式
CSS3透明背景+渐变样式 转载自博文:<CSS3透明背景+渐变样式> http://blog.csdn.net/netbug_nb/article/details/44343809 效果 ...
- --save-dev 与 --save区别
npm install 在安装 npm 包时,有两种命令参数可以把它们的信息写入 package.json 文件,一个是npm install --save另一个是 npm install --sav ...