树莓派充当mp3播放器

最近想着通过Raspberry Pi来充当mp3用,因为没有显示器,只有音箱,所以就把音箱直接接在Pi的3.5mm耳机接口上。可以在电脑上或者手机上通过网页来播放音乐。也许有人问,有了电脑或手机为什么要这个,因为也许电脑、手机的外放效果不怎么样,接音箱总归好一些。而且对于我这个懒人,就喜欢躺床上,希望通过手机来控制一切,所以才诞生了这个想法。

基本步骤:

1.安装系统,本人使用的是xbian,理论上其他系统也可以。如果已经装好系统,可以跳过这一步

2.安装mpg123

命令: apt-get install mpg123

安装完毕mpg123,拷贝一个mp3文件到Pi中,可以运行mpg123 xxx.mp3(xxx.mp3为mp3文件名)看看能否正常运行。

本人在运行的时候出现找不到输出口的问题,大概是声卡驱动没有正确加载,运行以下命令解决:

sudo modprobe snd-bcm2835

3.安装lnmp,其实这里只需要安装nginx和php就可以了。

参照我之前的帖子 http://blog.wo.ai/archives/194 来进行安装

或者简单运行如下程序:

apt-get install nginx php5 php5-fpm php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps
php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl

4.然后配置php sudo权限,这样php执行命令的时候不需要输入自己的密码

为 nginx,而想透过 PHP 发送irsend,用 root 输入指令 vi /etc/sudoers,
在档案最底加上以下一行:

www-data ALL=NOPASSWD: /usr/bin/mpg123

5.开始php旅程:

首先是index.php,用来遍历某个目录下所有的mp3文件,并显示出来:

//获取文件目录列表,该方法返回数组
function getDir($dir) {
$dirArray[]=NULL;
if (false != ($handle = opendir ( $dir ))) {
$i=0;
while ( false !== ($file = readdir ( $handle )) ) {
//去掉””.”、”..”以及带”.xxx”后缀的文件
if ($file != “.” && $file != “..”&&!strpos($file,”.”)) {
$dirArray[$i]=$file;
$i++;
}
}
//关闭句柄
closedir ( $handle );
}
return $dirArray;
}

//获取文件列表
function getFile($dir) {
$fileArray[]=NULL;
if (false != ($handle = opendir ( $dir ))) {
$i=0;
while ( false !== ($file = readdir ( $handle )) ) {
//去掉””.”、”..”以及带”.xxx”后缀的文件
if ($file != “.” && $file != “..”&&strpos($file,”.mp3″)) {
$fileArray[$i]=”/home/test/”.$file;
if($i==100){
break;
}
$i++;
}
}
//关闭句柄
closedir ( $handle );
}
return $fileArray;
}

读取mp3tag

function readmp3($mp3_file)
{
$fp=fopen($mp3_file,"rb"); //读取mp3文件
//首先判断是否有TAG,如果没有,那就没必要读取了,方法就是读取倒数128-126字节,看是否是TAG
//详情参看http://www.readlog.cn/archives/2961/
fseek($fp,-128,SEEK_END); //指针移到倒数128字节处
$tag=fread($fp,3); //读取倒数128-126字节位置的数据
if($tag=="TAG") //如果这3个字节是TAG,表明有TAG
{
$mp3=array();
//标题30个字节,从倒数125字节到倒数96字节
//现在直接读就可以了
$mp3['标题']=fread($fp,30);
//艺术家30个字节,从倒数95字节到66字节
$mp3['艺术家']=fread($fp,30);
//专辑30个字节,从倒数65字节到36字节
$mp3['专辑']=fread($fp,30);
//年份4个字节,从倒数35字节到32字节
$mp3['年份']=fread($fp,4);
//注释28个字节,从倒数31字节到4字节 (有的是30个字节,那就把倒数第2,3位归入注释了)
$mp3['注释']=fread($fp,28);
fseek($fp,1,SEEK_CUR); //跳过倒数第3位保留位
//第几首1个字节,倒数第2位
$mp3['编号']=ord(fread($fp,1));
//流派1个字节,就是倒数第一个字节了
//流派这里是存放的整型数据,可以写个函数来把数字变成具体的文字。
//具体含义参看http://www.readlog.cn/archives/2961/
$mp3['流派']=ord(fread($fp,1));
return $mp3;
}
}

生成mp3列表:

<?

//调用方法getDir(“./dir”)……可以是绝对路径也可以是相对路径
$filelist = getFile(“/home/test”);
//var_dump($filelist);
foreach($filelist as $file){
echo(“<li><input type=\”button\” onclick=\”checkMe(‘play.php?file=”.$file.”‘)\” value=\””.$file.”\”<br />”);
$mp3 = readmp3($file);
if($mp3){
echo($mp3[‘艺术家’].’-‘.$mp3[‘专辑’].’-‘.$mp3[‘标题’]);
}
}
?>
</ul>
<input type=”button” onclick=”checkMe(‘play.php?’)” value=”stop” />

页面基本完成了。

然后是play.php,根据传进来的文件名,通过后台播放:

<?php
$cmdline = “/usr/bin/sudo /usr/bin/killall mpg123 >/dev/null &”;
shell_exec($cmdline);
if($_GET[‘file’]){
$cmdline = “/usr/bin/sudo /usr/bin/mpg123 –loop -1 “.$_GET[‘file’].” >/dev/null &”;
echo($cmdline);
$output = shell_exec($cmdline);
echo($output);
}
?>

基本上大功告成了,这里的mp3文件名除了本地文件外,还可以是流媒体或者网址,都可以试试看。

英文中有个词是couch potato,我还是当bed potato吧。好好享受着音乐吧。

 

附:Raspberry Pi(树莓派)声音输出的设置

Raspberry Pi(树莓派)声音输出可以设置为自动,耳机输出,从HDMI输出三种,默认为自动

pi@aborn ~ $ sudo apt-get install alsa-utils
pi@aborn ~ $ sudo modprobe snd-bcm2835    #把声音模块加入内核
pi@aborn ~ $ sudo aplay /usr/share/sounds/alsa/Front_Center.wav
pi@aborn /opt/vc $ sudo amixer cset numid=3 2
numid=3,iface=MIXER,name=’PCM Playback Route’
; type=INTEGER,access=rw——,values=1,min=0,max=2,step=0
: values=2
pi@aborn /opt/vc $ sudo aplay /usr/share/sounds/alsa/Front_Center.wav
Playing WAVE ‘/usr/share/sounds/alsa/Front_Center.wav’ : Signed 16 bit Little Endian, Rate 48000 Hz, Mono
pi@aborn /opt/vc $ sudo amixer cset numid=3
numid=3,iface=MIXER,name=’PCM Playback Route’
; type=INTEGER,access=rw——,values=1,min=0,max=2,step=0
: values=0

pi@aborn /opt/vc $ sudo amixer cset numid=3 1
numid=3,iface=MIXER,name=’PCM Playback Route’
; type=INTEGER,access=rw——,values=1,min=0,max=2,step=0
: values=1

values取不同的值分别代表:
0=auto(自动), 1=headphones(耳机), 2=hdmi

php读取mp3文件信息 (转)

一个读取的程序。其实稍作改动,就可以变成读写的(id3v1),id3v2复杂的多,以后看情况再写吧。
<?php
$file=”回到我身边.mp3″; //要读取的文件–俺偶像的
$mp3info=readmp3($file); //获得文件信息,数组
print_r($mp3info); //输出数组
function readmp3($mp3_file)
{
$fp=fopen($mp3_file,”rb”); //读取mp3文件
//首先判断是否有TAG,如果没有,那就没必要读取了,方法就是读取倒数128-126字节,看是否是TAG
//详情参看http://www.readlog.cn/archives/2961/
fseek($fp,-128,SEEK_END); //指针移到倒数128字节处
$tag=fread($fp,3); //读取倒数128-126字节位置的数据
if($tag==”TAG”) //如果这3个字节是TAG,表明有TAG
{
$mp3=array();
//标题30个字节,从倒数125字节到倒数96字节
//现在直接读就可以了
$mp3[‘标题’]=fread($fp,30);
//艺术家30个字节,从倒数95字节到66字节
$mp3[‘艺术家’]=fread($fp,30);
//专辑30个字节,从倒数65字节到36字节
$mp3[‘专辑’]=fread($fp,30);
//年份4个字节,从倒数35字节到32字节
$mp3[‘年份’]=fread($fp,4);
//注释28个字节,从倒数31字节到4字节 (有的是30个字节,那就把倒数第2,3位归入注释了)
$mp3[‘注释’]=fread($fp,28);
fseek($fp,1,SEEK_CUR); //跳过倒数第3位保留位
//第几首1个字节,倒数第2位
$mp3[‘编号’]=ord(fread($fp,1));
//流派1个字节,就是倒数第一个字节了
//流派这里是存放的整型数据,可以写个函数来把数字变成具体的文字。
//具体含义参看http://www.readlog.cn/archives/2961/
$mp3[‘流派’]=ord(fread($fp,1));
return $mp3;
}
}
?>

无根浮萍

周末回到SH整理了两天东西,然后将所有打包好的东西发物流回去,居然有587公斤,这是来SH近10年存下来的。发完快递以后,不知为什么心情很乱,不想在SH多停留一分钟,打电话给航空公司改早一班飞机到SZ。到飞机上也一直很乱,突然明白“家”没了。回国两年来,一直在外面出差,孩子妈和孩子一直在SH,心理上那个“家”还在SH。前不久他们回去了,SH那个“家”空在那里,至少觉得他们会回去,也还算一个家。今天把所有家当发回去,突然发现象征意义的那个家没了,难怪会乱。虽然孩子妈在那里也找了房子,我也可以周末回去,但冥冥中告诉我,那不是我的家,只是个住所而已。

很早以前听说,走到哪,家就在哪,那应该是在单身的时候吧。

寻找公历农历相同的日子

今年大家都在热炒1986年的公历和今年的一样,但是农历却不一样。因为公历每四年闰一天,每周有七天,所以大概是28年同一次,农历是19年同一次(解释在下面),理论上农历和西历要完全相同,大概需要19*28=532年。理论上公元1482年的西历和农历都和今年相同。实际上28年重复一次,也不是靠谱的,因为每年的日子实际上是个小数,公历四年一闰,但是百年反而不一定闰了,规则是如果年份可以被100除尽,还需要被400除尽才闰,这样导致公历也会相差,比如1902,1930,1958,1986,2014这几年日历相同,因为1900年不是闰年,导致1874年比2014年的元旦晚了一天。所以翻遍万年历,几乎不可能找到农历公历完全相同的日子。

2014/1/1 周三,农历十二月初一

1482/1/1 周四,农历十二月初三

950/1/1周四,农历十二月初四

418/1/1周一,农历十二月初八

另外,澄清一点,公历或者西历是太阳历,所以可以称作阳历,而农历不但根据月亮公转地球的周期,还要计算地球公转太阳的周期,所以准确的说,应该是阴阳历,所以大众普遍说的阴历其实是不准确的。

下面是解释为什么农历中十九年七闰及公历四年一闰的原因:

转载自

http://destiny.xfiles.to/ubbthreads/ubbthreads.php/topics/610122

除了你出生的那一年之外,大家有沒有遇過你西曆生辰的那一天又是你的農曆生辰呢?未遇過?這不出奇。因為根據曆法,西曆和農曆每隔 19 年才循環一次,如果你的年齡未滿 19 歲,自然不會遇上西曆生辰和農曆生辰在同一天出現的情況了。

可能大家會懷疑,為甚麼一定要等 19 年,西曆和農曆才會循環一次呢?為了明白 19 年循環的奧秘,我們先就要明瞭倒底「西曆」和「農曆」是怎樣制定出來的。首先,讓我們看看「西曆」:

我們現時所採用的「西曆」,顧名思義,就是一套從西方傳入的曆法系統。遠在古羅馬(甚至是更早的)時期,當時的歐洲人就已經將地球環繞太陽公轉一周所需的時間定為「一年」。通常我們都說 1 年有 365 日,即是說地球自轉了 365 次(日),它就會環繞太陽公轉 1 次(年)。如果地球自轉和公轉之比,剛好是一個整數,那麼一切就好辦了,但很可惜,經過仔細的天文觀測後發現,地球環繞太陽公轉所需的準確時間應為 365 日 5 小時 48 分 46 秒,即約 365.2422 日。故此,1 年有 365 日的想法,和地球公轉所需的時間,實際上有 0.2422 日的差別。

相信大家都知道,我們每隔 4 年就會在第 4 年中增加一日(即該年的 2 月 29 日),目的就是為了彌補上述的差別。注意:0.2422 ´ 4 = 0.9688,而 1 – 0.9688 = 0.0312 日,即約等於 44 分 56 秒。換句話說,使用了「四年一閏」的曆法,我們每隔 4 年就可以將上述的差別減少至 4 年才相差 44 分 56 秒,相信這是一個很合理的處理辦法了。

由於「西曆」是按照太陽和地球的關係而制定出來的,故此亦有人將「西曆」稱為「陽曆」。而為了方便後面的討論,我將地球公轉所需的時間(即 365.2422 日)稱為 1 個「太陽年」。

「農曆」就比較麻煩。有人稱「農曆」為「陰曆」,這是因為「農曆」主要是根據月球環繞地球公轉所需的時間而制定出來的。同樣,據觀測,月球環繞地球公轉一周所需的時間亦不是一個整數,而是等於 29 日 12 小時 44 分 2.8 秒,即約 29.5306 日。故此,在農曆裏面,1 個月有時會有 29 日,有時又會有 30 日。這要看每次月缺和月圓的時間才可定出一個月到底有多少日。通常,我們會將月圓的那一天定為每個月的第 15 日。同樣,為了方便後面的討論,我將月球環繞地球公轉所需的時間(即 29.5306 日)稱為 1 個「太陰月」。

將 1 個太陽年和 1 個太陰月相除,得 365.2422 ¸ 29.5306 = 12.368262,由此可知 1 個太陽年比 12 個太陰月多出 0.368262 個太陰月,約 10 日 21 小時。在這裏,問題來了:如果我們將 1 個農曆年定為 12 個月,那麼每過 1 年,我們就要提早差不多 11 日過新年了!這樣做,會令到我們使用農曆時出現很多混亂和困難的情況。例如:農夫發覺今年農曆 3 月 1 日天氣回暖,春天到了,適合播種,那麼到了第二年就要改於 3 月 12 日播種,第三年就要改於 3 月 23 日,如此類推。十年後就要在 7 月才開始耕種,二十年後就要到 11 月了!

為了解決上述的困難,農曆的曆法亦好像西曆「四年一閏」的制度一樣,在適當的時候就會在某一年之中加插多一個月(即閏月)來調節上述的差距。至於哪一年需要多加一個閏月,它的推算方法亦十分簡單,就是直接將每年多出來的時間(即 0.368262 個太陰月)累積地加起來,如果剛好超過 1 個太陰月,就可以在該年加插一個閏月了。

例如:第 1 年多了 0.368262 個太陰月,第 2 年就會多 0.736524 個太陰月,第 3 年將會多出 1.104786 個太陰月。這時剛好多於1個太陰月,所以我們就在第 3 年中加添一個閏月,因而得到農曆「三年一閏月」的規律。

但「三年一閏月」這個方法並不完美,原因是即使增加了 1 個閏月,3 年後仍和實際的太陽年相差了 0.104786 個太陰月,約 3 日 2 小時。這個差距依然很大。為了建造一個更好的曆法,我們可以繼續算下去,從而得到下表:

年數 累積差額(個太陰月)
3 1.104786
6 2.209572
8 2.946096
11 4.050882
14 5.155668
16 5.892192
19 6.996978

這樣,我們就計算出農曆年和太陽年之間一個更準確的關係了。從上表可以見到,當過了 8 年後,雖然差額祇有 2.946096 個太陰月,仍未足 3 個太陰月,但這個數字卻和 3 非常接近,故此,在農曆的曆法中,亦有「八年三閏月」的規定,即除了在第 3 和第 6 年分別插入 1 個閏月外,亦在第 8 年再加插多 1 個閏月。這時候,我們祇是隔了一年,就已經有多 1 個閏年了。類似地,到了第 16 年,就應該有 6 個閏月了。

注意:按「八年三閏月」的規定推算,8 年後太陽年和農曆年應該相差了 3 – 2.946096 = 0.053904 個太陰月,即約 1 日 14 小時。亦即是說,經過 8 年後,農曆年和太陽年其實祇有一至兩天的差距。大家是否記得你們 8 歲的那一年,你們的西曆生辰祇比農曆生辰早了 1 天或 2 天到臨呢?看過以上的計算,大家就應該明白,這個現象是基於甚麼原因而造成的了。

但一個更準確的結果,應該出現在第 19 年了。如果我們定「19 年 7 閏月」,那麼太陽年和農曆年就祇相差 7 – 6.996978 = 0.003022 個太陰月,即約祇有 2 小時!試想想:在長長 19 年的歲月中,若依照「19 年 7 閏月」的方法,最後兩種曆法其實祇相差 2 小時,這是一個多麼精確的結果!因此,每逢 19 或 19 倍歲數生辰的時候,西曆生辰和農曆生辰就有機會在同一天出現了。

例如:2003 年的 2 月 1 日是農曆年的正月初一。19 年後,即 2022 年的 2 月 1 日那天亦剛好是農曆正月初一!換句話說,在 2003 年 2 月 1 日出生的人,到了 2022 年 19 歲生辰那天,就會同日慶祝兩個曆法上的生辰了。(大家不妨查一查,你們 19 歲的那一年,西曆生辰和農曆生辰又是否重疊在同一天呢?)不過,如果我們倒數 19 年卻發現,1984 年的正月初一卻在 2 月 2 日,而並非 2 月 1 日!這又是甚麼原因呢?

其實理由也很簡單,這是因為「太陽年」和「太陰月」的日數都不是整數,而我們實際使用的西曆和農曆,每一年和每一個月的日數都必須是整數的。例如:西曆每逢第 4 年就會多加一日,而農曆的月份亦有長有短,有時會有 29 日,有時又會有 30 日,所以會令到部分的日子會有些微的出入,亦引致有些人即使他們到了 19 歲時,西曆生辰和農曆生辰仍然會有一天的差距。

例如:2000 年的 2 月 29 日是農曆的正月 25 日,3 月 1 日是正月 26 日。19 年後,即 2019 年,該年根本不是閏年,該年沒有 2 月 29 日,而該年的 3 月 1 日則變成農曆的正月 25 日。所以在 2000 年那幾天出生的人,到了 19 歲,亦沒有機會在同一天慶祝兩個生辰了。

就以我本人而言,在我 19 歲的那一年,農曆生辰比西曆生辰早了一天出現,即使到了 38 或 57 歲,這兩個生辰亦不會重疊在一起。這的確是一件令我感到遺憾的事情!

=======================

我测试了一下,如果说某年正好是西历的闰年,之后的的日子就被打乱了,西、农历会相差一天。

乱弹

拣尽寒枝不肯栖 飘渺孤鸿影

曲巷跳鱼 圆荷泻露 寂寞无人见

谁伴明窗独坐?我共影儿两个。灯尽欲眠时,影也把人抛躲。无那,无那。好个凄惶的我!

凭阑久,疏烟淡日,寂寞下芜城

乡梦断,旅魂孤,峥嵘岁又除

2014元旦

一大早起来就摔了一跤,觉得应该给自己找点事做,变换一下今天的心情,干脆来个HK半日游,。
过关的时候人还不是太多,可能因为中午的缘故。

来到时代广场,还留下了不少新年夜的气氛,不少小朋友在这里玩耍拍照。

20140102-181938.jpg

 

星光大道的经典塔楼。

20140102-181839.jpg

 

择日不如撞日,每周三免费这种事情居然让我碰到了。

20140102-181819.jpg

 

测试从手机发表。

春暖花开

2014就这么偷偷摸摸的来了,一大早就摔了俩跟头,也许就是把2014年的厄运都这么过去了吧。

外面现在阳光灿烂,虽然还算是冬天,还是向往春暖花开的时候。按照往年的惯例,开始整理打扫卫生,该洗的洗,该晒的晒。

2013年的好的也好,坏的也好,都这么过去吧,希望2014是个新的开始。

忘れられないひととことが色々ですけど、終わっちゃった。感謝すると謝罪する機会がありませんが、申し訳ございませんでした。

http://m6.file.xiami.com/21/2021/161000846/1771690321_4283785_h.mp3

歌名:春暖花开

作词:梁芒
作曲:洪兵
演唱:那英

春暖花开歌词:

如果你渴求一滴水
我愿意倾其一片海
如果你要摘一片红叶
我给你整个枫林和云彩
如果你要一个微笑
我敞开火热的胸怀
如果你需要有人同行
我陪你走到未来
春暖花开
这是我的世界
每次怒放
都是心中喷发的爱
风儿吹来
是我和天空的对白
其实幸福
一直与我们同在

如果你要一个微笑
我敞开火热的胸怀
如果你需要有人同行
我陪你走到未来
春暖花开
这是我的世界
每次怒放
都是心中喷发的爱
风儿吹来
是我和天空的对白
其实幸福
一直与我们同在

春暖花开
这是我的世界
生命如水
有时平静 有时澎湃
穿越阴霾
阳光洒满你窗台
其实幸福
一直与我们同在
我的世界

mpg123的循环播放

MPG123,听音乐最好能使用一个表(文件)把要播放的歌曲目录存在表里面:view plaincopy to clipboardprint?
find . -name “*.mp3” | sed ‘s/\.\///’ | sort > list.lst
find . -name “*.mp3” | sed ‘s/\.\///’ | sort > list.lst  播放的时候就可以:view plaincopy to clipboardprint?
mpg123 –list list.lst
mpg123 –list list.lst如果要循环的话可以加入–loop选项:view plaincopy to clipboardprint?
mpg123 –loop -1  songname.mp3
//-1(<0)的数表示无限循环,也可以指定确定的次数。只能是单首循环。
//这个–loop 参数如果用来播放List(文件)中的歌曲时
//是不能够达到重头到尾的重复播放的效果的,只是循环第一首。

//如果要循环目录内容的话,目前可以:
mpg123 –list list.lst -Z
//用于随机循环播放
mpg123 –loop -1  songname.mp3
//-1(<0)的数表示无限循环,也可以指定确定的次数。只能是单首循环。
//这个–loop 参数如果用来播放List(文件)中的歌曲时
//是不能够达到重头到尾的重复播放的效果的,只是循环第一首。//如果要循环目录内容的话,目前可以:
mpg123 –list list.lst -Z
//用于随机循环播放