以前我欣赏古典音乐都是听的CD,因而珍藏了不少光盘以及下载到电脑上的ape与flac格式的音乐文件。随着手机硬件性能(如电池续航能力、处理器速度、音质、存储容量等)和软件功能(音乐播放器对于曲目的管理)的提升,便需要考虑如何将这些资源转换成高质量的mp3文件放到手机上聆听。本文介绍如何基于GNU/Linux下的Audacity、k3b、easytag软件,以及自己写的Bash脚本程序来实现此功能。

从光盘抓取音乐并转为mp3

k3b是KDE环境下默认的光盘刻录与抓取软件。其界面如下图所示。

选择菜单Tools中的Rip Audio CD,我们可用它直接从CD光盘上抓取出wav文件。接下来,打开Audacity音乐编辑软件,将抓取的多个wav文件导入(而非打开)为多个音轨。再选择菜单Files中的Export Multiple,将导出格式选为mp3,导出选项中的采样频率设为320 kbps,然后点击导出即可完成转换。如下图所示。

最后,打开easytag软件,填写mp3文件的曲目信息(ID3 Tag)。注意,点击信息文本框旁边的小圆点,可以一次性地将设置应用到所有选中的文件。如下图所示。

将ape或flac文件转为mp3文件

一般下载的CD Rip文件是ape或flac格式的,具有无损音质。可若直接将其拷到手机上,一是某些软件可能不支持这两种格式,二是它们所占用的存储空间太大了,三是由于它们也不包含类似于mp3文件的ID3 tag信息,从而无法被音乐播放软件自动根据专辑名或作曲家名而自动分类管理。因此,有必要将ape和flac文件按曲目拆分并转换为mp3格式,填写曲目信息后再导入手机。

可以看出,这里首先需要解决的是ape与flac文件的曲目拆分问题。一般来说,与它们一同下载的还会有个扩展名为cue的文件。此文件保存了CD的曲目信息,包括音乐风格(GENRE)、制作年份(DATE)、表演者(PERFORMER)、专辑/CD名称(TITLE)、ape或flac文件的名称(FILE),以及每个音轨(TRACK)的标题(TITLE)、表演者(PERFORMER)和开始时间(INDEX 01)。如下所示:

REM GENRE Classical
REM DATE 1991
REM DISCID 9B0E701C
REM COMMENT "ExactAudioCopy v0.95b4"
PERFORMER "Wächter, Sutherland, Schwarzkopf, Taddei, Alva, Sciutti, Frick"
TITLE "Don Giovanni - Giulini 1/3"
FILE "CDImage.ape" WAVE
  TRACK 01 AUDIO
    TITLE "Sinfonia"
    PERFORMER "Wächter, Sutherland, Schwarzkopf, Taddei, Alva, Sciutti, Frick"
    INDEX 01 00:00:00
  TRACK 02 AUDIO
    TITLE "Notte e giorno faticar"
    PERFORMER "Wächter, Sutherland, Schwarzkopf, Taddei, Alva, Sciutti, Frick"
    INDEX 01 06:18:07
  TRACK 03 AUDIO
    TITLE "Non sperar, se non m'uccidi"
    PERFORMER "Wächter, Sutherland, Schwarzkopf, Taddei, Alva, Sciutti, Frick"
    INDEX 01 07:58:31

需要说明的是,某个音轨的信息中可能同时含有INDEX 00与INDEX 01,那么该曲目实际的开始时间是由INDEX 01来指定的。INDEX 01的值比INDEX 00要大一些,目的是为了跳过该曲目前端的空白部分。由INDEX 01指定的时间分为三部分:分钟:秒:1/75秒。

在搞清楚cue文件的格式后,我们再来看音乐编辑软件Audacity所拥有的一个功能:我们可以通过导入包含各音轨信息的标签(label)文件,再选择Export Multiple,则可以将整个的ape或flac文件作拆分并转换为mp3文件。该标签文件的格式如下:

0.000000    0.000000    Sinfonia
378.093333    378.093333    Notte e giorno faticar
478.413333    478.413333    Non sperar, se non m'uccidi

其中,每一行代表一个曲目。每一行中的第一列与第二列的内容相同,都是该音轨的开始时间,单位是秒。第三列则是该曲目的标题。

从cue到label文件的转换可以在这里在线完成,但毕竟不太方便。所以,我写了一个脚本程序cue2lbl.sh,来实现同样的功能。源代码如下:

#!/bin/bash

script_name="cue2lbl.sh"
script_usage=$(cat <<EOF
$script_name [OPTIONS] cue_file
EOF
)
script_function=$(cat <<EOF
Convert a cue CD index file to Audacity label file.
EOF
)
script_doc=$(cat <<EOF
Script documentation.
-h Display this help.
-o Specify output lable file.
EOF
)
script_examples=$(cat <<EOF
$script_name -o music.txt music.cue
EOF
)
state_prefix="==="
warning_prefix="***"
error_prefix="!!!" function display_help() {
if [ -n "$script_usage" ]; then
echo -e "Usage: $script_usage"
fi if [ -n "$script_function" ]; then
echo -e "$script_function"
fi if [ -n "$script_doc" ] ; then
echo -e "\n$script_doc"
fi if [ -n "$script_examples" ]; then
echo -e "\nExamples"
echo -e "$script_examples"
fi
} # Output label file
lbl_file="" # Process command options
while getopts ":ho:" opt; do
case $opt in
h ) display_help
exit 0 ;;
o ) lbl_file=$OPTARG ;;
\? ) display_help
exit 1 ;;
esac
done
shift $(($OPTIND - 1)) # Start execute the command
if [ -z "$lbl_file" ]; then
lbl_file="${1%cue}txt"
fi # Label file first time writing
lbl_file_1st_write=1 # Searched state: 0 for start; 1 for track; 2 for title; 3 for index.
searched_state=0 declare -i track_time_minute=0 track_time_second=0 IFS=$'\n'
for line in `grep -i "\(INDEX\)\|\(TITLE\)\|\(TRACK\)" "$1"`; do
case $searched_state in
0 )
if [ -n "`echo "$line" | grep -i TRACK`" ]; then
searched_state=1
fi ;;
1 )
if [ -n "`echo "$line" | grep -i "TITLE"`" ]; then
# Remove blanks at the beginning and end of a line
line=`echo "$line" | gawk -f /usr/local/bin/scripts/rmblank.awk`
# Get title
track_title=`echo "$line" | gawk -f /usr/local/bin/scripts/cue2lbl_get_title.awk`
track_title=`echo "$track_title" | gawk -f /usr/local/bin/scripts/rmblank.awk | tr -d \"`
searched_state=2
fi ;;
2 )
if [ -n "`echo "$line" | grep -i "INDEX"`" ]; then
# Remove blanks at the beginning and end of a line
line=`echo "$line" | gawk -f /usr/local/bin/scripts/rmblank.awk`
# Get track index
line=`echo "$line" | gawk -f /usr/local/bin/scripts/cue2lbl_get_index.awk`
track_index=`echo "$line" | gawk -f /usr/local/bin/scripts/rmblank.awk | cut -f 1 -d " " | tr -d " "`
if [ "$track_index" = "01" ] || [ "$track_index" = "1" ]; then
# Get track time
track_time=`echo "$line" | gawk -f /usr/local/bin/scripts/rmblank.awk | cut -f 2 -d " " | tr -d " "`
track_time_minute=`echo "$track_time" | cut -f 1 -d ":" | gawk '{if (match($0, "^0+$") != 0) {print "0";} else {gsub("^0+", ""); print}}'`
track_time_second=`echo "$track_time" | cut -f 2 -d ":" | gawk '{if (match($0, "^0+$") != 0) {print "0";} else {gsub("^0+", ""); print}}'`
track_time_sub_second=`echo "$track_time" | cut -f 3 -d ":" | gawk '{if (match($0, "^0+$") != 0) {print "0";} else {gsub("^0+", ""); print}}'`
track_time_total_seconds=$(($track_time_minute * 60 + $track_time_second))
track_time_sub_second=`echo "scale=6; $track_time_sub_second / 75" | bc`
if [ "$track_time_sub_second" = "0" ]; then
track_time_sub_second=".000000"
fi
track_time_total_seconds=`echo "$track_time_total_seconds$track_time_sub_second"`
fi
fi if [ -n "`echo "$line" | grep -i "TRACK"`" ]; then
# Print collected track information
if [ "$lbl_file_1st_write" = "1" ]; then
echo -e "$track_time_total_seconds\t$track_time_total_seconds\t$track_title" > "$lbl_file"
lbl_file_1st_write=0
else
echo -e "$track_time_total_seconds\t$track_time_total_seconds\t$track_title" >> "$lbl_file"
fi searched_state=1
fi ;;
esac
done # Print the last collected track information
if [ "$lbl_file_1st_write" = "1" ]; then
echo -e "$track_time_total_seconds\t$track_time_total_seconds\t$track_title" > "$lbl_file"
else
echo -e "$track_time_total_seconds\t$track_time_total_seconds\t$track_title" >> "$lbl_file"
fi

为了完成字符串的匹配,该脚本程序中用到了几个gawk程序,分别如下:

1. 移除行首与行尾的空白字符:

{
gsub("(^[[:blank:]]+)|([[:blank:]]+$)", "");
print;
}

2. 删除INDEX:

/^(INDEX)|(index)/ {print gensub("^(INDEX)|(index)[[:blank:]]+", "", 1);}

3. 删除TITLE:

/^(TITLE)|(title)/ {print gensub("^(TITLE)|(title)[[:blank:]]+", "", 1);}

至此,有了label文件,便可用Audacity将ape和flac转换生成多个mp3文件了。

将mp3文件导入手机

目前我的手机上使用的是“酷我音乐”播放器,可以直接通过Wifi由电脑向手机传歌。如下图所示,打开“酷我音乐”后,点击页面底部的“电脑-手机传歌”:

然后在电脑上打开浏览器,输入提示的地址,添加文件即可。

在GNU/Linux下将CD音乐转为mp3的更多相关文章

  1. 我在GNU/Linux下使用的桌面环境工具组合

    为了使GNU/Linux桌面环境下加载的程序较少以节省内存资源和提高启动时间,我目前并不使用重量级的桌面环境KDE和Gnome,甚至连登录窗界面gdm或xdm都不用,而是直接启动到控制台,登录后调用s ...

  2. GNU/Linux下Freeplane的界面渲染问题

    如下图所示,思维导图软件Freeplane在GNU/Linux下默认的界面渲染效果是很差的,即便将Preferences → Appearance → Antialias设置为Antialias al ...

  3. 在GNU/Linux下制作Windows 10安装U盘

    今年春节回家期间,我需要将家里的一台安装了Debian Stretch的ZaReason笔记本电脑更换为Windows 10系统,好让爸妈从老台式机上的XP系统升级到新的平台上来.回家前,小仙女已在微 ...

  4. Gnu Linux下文件的字符编码及转换工具

    /*********************************************************************  * Author  : Samson  * Date   ...

  5. 在GNU/Linux下使用Lilypond排版简谱

    尽管GNU/Linux并非无所不能,但确实能在很多时候提供免费.开放的解决方案.这两天我想做一个简谱,在网上搜索乐谱排版软件,发现了基于GPL协议的Lilypond软件.只不过Lilypond是用来做 ...

  6. Linux下一个CD翻录 创CUE 压缩flac攻略

    于Windows我们通常使用较低EAC翻录压缩发生器CUE找工作的步骤,但在Linux在稍微有点麻烦.每一步,我们需要自己做.经过我的反复尝试寻找和总结了相当不错的方法,使用软件和步骤如下面的. 使用 ...

  7. arch linux下网易云音乐运行没反应,只能使用root用户运行

    本文通过MetaWeblog自动发布,原文及更新链接:https://extendswind.top/posts/technical/netease_music_can_not_open 最近打开网易 ...

  8. GNU/Linux下LVM配置管理以及快照卷、物理卷、卷组、逻辑卷的创建和删除

    LVM是Linux环境中对磁盘分区进行管理的一种机制,是建立在硬盘和分区之上.文件系统之下的一个逻辑层,可提高磁盘分区管理的灵活性.最大的优点是在不损伤数据的前提下调整存储空间的大小. 本篇主要讲述L ...

  9. 在GNU/Linux下设置与定时更换桌面壁纸

    1 简介 在电脑桌面设置一组可以定时更换的壁纸已经不是什么新奇的功能了.比如,Windows 7.KDE桌面环境都可以实现这样的效果.可是,自己目前使用的Debian系统并未安装KDE.GNOME这样 ...

随机推荐

  1. 项目结构的设计(iOS篇)

    项目结构的设计(iOS篇) 本文附带源码:YoungHeart-Chapter-02.zip 在设计任何一个框架之前,都应规划好项目结构. 假定Git作为我们的项目管理工具.我们要建立两个仓库,一个用 ...

  2. JS获取ckeditor4.x里的值

    项目中有这样一个需求,使用ckeditor可以上传图片,需要在前端验证一下不可上传多于5张图片. 以下是查看源代码所看到的ckeditor里的值 <p>AAAAA</p> &l ...

  3. infiniband学习总结

    一.什么是infiniband InfiniBand架构是一种支持多并发链接的“转换线缆”技术,它是新一代服务器硬件平台的I/O标准.由于它具有高带宽.低延时. 高可扩展性的特点,它非常适用于服务器与 ...

  4. 从UI开始

    虚拟化平台cloudstack(8)——从UI开始   UI ucloudstack采用的是前后端分离的架构,就是说前端可以选择使用web.swing甚至其它的界面,都可以. 我们来看cloudsta ...

  5. ARP 和 RARP

    ARP 和 RARP 1.ARP      地址解析协议(Address Resolution Protocol,ARP)是在仅知道主机的IP地址时确地址解析协议定其物理地址的一种协议.      在 ...

  6. MySQL中函数、游标、事件、视图基本应用举例(代码)

    MySQL中function用户自定义函数c,fun,fun是面向过程的实现方式只能传入参数,或不传入参数,不能传出参数,必有返回值函数中是不能有create table drop table之类的语 ...

  7. openbr on linuxmint13/ubuntu12.04/debian7 x64 facial recognition [Compile from source!!!]

    Openbr is a great project for facial detecting. System: linuxmint 13 x86_64 Face recognition,  motio ...

  8. 微软必应借PK谷歌突围中国搜索市场

    Bing“必应”是微软2009年推出的搜索品牌(http://www.bing.com),它取代的是同门师兄Live Search.进入2013年,在国内及好莱坞的多部大片里面,我都看到了Bing搜索 ...

  9. 【Machine Learning】单参数线性回归 Linear Regression with one variable

        最近开始看斯坦福的公开课<Machine Learning>,对其中单参数的Linear Regression(未涉及Gradient Descent)做个总结吧. [设想]    ...

  10. Solr之NamedList 简单介绍与实例解析

    大家都知道,Solr是一个基于Lucene高可配置的搜索服务器,大部分参数值以及相关优化等等都可以在solrconfig.xml中配置,那么就需要一个能够很快的进行解析和读取配置文件内容的数据结构,为 ...