2012年1月27日 星期五

HTK Basic Tutorial (1)

研究了下HTK,有个非常好的入门教程:agp1.hx0.ru/arts/HTK_basic_tutorial.pdf 
我的系统是Fedora 16. 由于音频驱动的不同,不可能依葫芦画瓢,照着教程一步步来.
网上也没有很详细的过程,希望后来者省却这些麻烦,以下详细介绍整个过程:
第一步:录制训练音频并标记
教程里使用的是HTK里的HSLab,但是似乎HSLab支持的是OSS驱动,而我的电脑使用的是Alsa(?),试了一些方法,无论如何也没有办法让HSLab工作,其间按照一些Posts误删一些重要的包因此重装系统,痛不欲生(夸张了).当按下Rec键时,出现以下错误:
  ERROR [+6006]  InitAudi: Cannot open OSS audio device /dev/dsp
 FATAL ERROR - Terminating program HSLab

我的方法是使用开源软件Audacity来录制音频.然后保存为yes01.wav yes02.wav... no01.wav no02.wav... yes no 各十个
然后是制作音频的Label,即标出该音频那一段是sil(lence),那一段是yes(no).
可以手动做,但是蛮吃力的,我使用audacity自带的标记功能:


选择一段音频,然后按ctrl-b,然后输入标签名,如(sil,no,yes) ,然后在File里有一个Export Label选项,保存为txt格式.打开之后:
 0.000000    0.470889    sil
0.470889    0.800729    no
0.800729    2.634376    sil
而htk要求的label时间是以100ns为单位的,我写了个python转换程序(初学python,献丑了):
import math
import sys
from cStringIO import StringIO

def txt2lab(filename):
    f_in = open(filename,'r')
    f_out = open(filename[:-3] + 'lab', 'w')
    text_f_in = StringIO(f_in.read())

    for line in text_f_in:
        data = line.split('\t')
        start = int(math.floor(float(data[0])*10000000))
        end = int(math.floor(float(data[1])*10000000))
        f_out.write(str(start) + '\t' + str(end) + '\t' + data[2])

if __name__ == '__main__':
    filename = sys.argv[1]
    txt2lab(filename)
然后批量转换之前手动生成的label(.txt)文件:
for file in *.txt; do python txt2lab.py $file; done
文件结构参照原pdf,即所有的wav存放在data/train/sig下,所有的lab存放在data/train/lab下

2012年1月22日 星期日

Python IDE(Vim)

网上已经有一个类似的,也很全(http://blog.dispatched.ch/2009/05/24/vim-as-python-ide/)
蛮完整的,我简单谈一下我的使用感受.
我的.vimrc是按照amix的终极配置改的.其中的保存python后,删除空白很有效.
然后为了编辑python,我按照所附链接下载了以下插件:minibuffer,和Taglist,两个都很好用,没有问题.然后我想方便autocompletion,于是又装了supertab,结果tab不出completion,很让人恼火.后来发现,我按照amix的装了一个snipMate的插件,与之冲突了.觉得我还是喜欢自己敲代码,就把snipMate删了.终于可以tabcompletion了.
作为IDE,最重要的是能够debug,然而我试了文中提到的Vimpdb,无论如何无法使其工作.首先是文档格式问题,我照着网上的使用dos2unix转换了两个文件,但是,之后,我试着debug这个插件,发现对我这个python菜鸟来说,太繁复了,不想浪费时间.顺便一提,这个插件的作者编码的习惯不好,缩进是用tab键而不是4空格.当我试图插入自己的代码时,总是报错,发现就是源于他使用的tab缩进导致的.用vim自带的retab解决问题.但是实在没心思再debug了.网上很多人也抱怨这个插件的.
于是google了,发现一些walkaround,试了几个,都不怎么好用.(Vimdebug...),
发现可行的办法是,直接使用pdb得了,然后在代码里添上pdb.set_trace()设定端点,然后pdb下调试.无可奈何阿.不过还是想偷点懒,找到别人的.vimrc(http://www.2maomao.com/blog/win32-vim-debug-python/),思路就是快捷添加set_trace(),或者快捷删除set_trace()取消端点,然后设定快捷运行程序启动pdb(:!python %),我略微修改了map,使用f2设断点,f3取消断点,f5运行,似乎找到了以前写c作业的感觉.
我发现作者写得时候或者po上网的时候,出现了一个bug:
python << EOF
import time
import vim
def SetBreakpoint():
    nLine = int( vim.eval( 'line(".")'))
    strLine = vim.current.line
    i = 0
    strWhite = ""
    while strLine[i] == ' ' or strLine[i] == "\t":
        i += 1
        strWhite += strLine[i]
    vim.current.buffer.append(
       "%(space)spdb.set_trace() %(mark)s Breakpoint %(mark)s" %
         {'space':strWhite, 'mark': '#' * 30}, nLine - 1)
    for strLine in vim.current.buffer:
        if strLine == "import pdb":
            break
        else:
            vim.current.buffer.append( 'import pdb', 0)
            vim.command( 'normal j1')
            break
vim.command( 'map :py SetBreakpoint()')

def RemoveBreakpoints():
    nCurrentLine = int( vim.eval( 'line(".")'))
    nLines = []
    nLine = 1
    for strLine in vim.current.buffer:
        if strLine == 'import pdb' or strLine.lstrip()[:15] == 'pdb.set_trace()':
            nLines.append( nLine)
        nLine += 1
    nLines.reverse()
    for nLine in nLines:
        vim.command( 'normal %dG' % nLine)
        vim.command( 'normal dd')
        if nLine < nCurrentLine:
            nCurrentLine -= 1
    vim.command( 'normal %dG' % nCurrentLine)
vim.command( 'map :py RemoveBreakpoints()')
vim.command( 'map :!python %')
EOF

其中,开头的i+=1(红色粗体)应该和后面一行对调,string的开始是从0开始,而不是1.总得来所,作者写得挺好的,也挺好用的,在此写过.
不过我觉得在gvim下pdb似乎会有点问题,其他buffer会不更新,僵在那.要么编辑就在gvim,debug还是在另开窗口在terminal下比较好.Debug似乎不是Vim的强项,首先他是个文本编辑器.
另外,推荐一下Vim配色,molokai,很有现代感,但是可能颜色太鲜艳.

2012年1月3日 星期二

Linux下分割APE,并转档至ALAC

(1)如果是中文专辑,.cue文件通常是乱码的 首先确定.cue的编码 我使用vim 在.vimrc中添加:
            set fileencodings=utf-8,gb2312,gbk,gb18030
            set termencoding=utf-8
            set encoding=prc
这样打开.cue后不再乱码 然后输入:set fileencoding 出现编码方式,我的出现euc-cn的编码方式,是GB2312的别名
或者使用enca
            $ enca -L zh_CN 文件名.cue
然后进行转码:使用iconv
            $ iconv -f GB2312 -t UTF-8 文件名.cue -o 输出文件名.cue
(2)分割整个ape文件(参照:http://www.cnblogs.com/stephenjy/archive/2010/03/01/1675835.html)
安装shntool,以及mac解码器。 shntool可以用apt-get(ubuntu)或者yum(fedora)安装 mac解码器必须编译安装。直接yum install mac安装后,分割不成功。
到 http://shnutils.freeshell.org/shntool/ 下载 Helperprogram下的ape的patchrc 依据info,
执行: $ CXXFLAGS="-DSHNTOOL" ./configure
             $ make
             $ make install
分割文件
             $ shntool split -t "%n.%p-%t" -f 文件名.cue -o ape -i ape 文件名.ape
(3)转档
安装ffmpeg(yum install)
执行:
             $ ffmpeg -i 文件名.ape -acodec alac 文件名.m4a
如果嫌逐个麻烦:
到该文件夹下,首先找出类型为.ape的小于200M的单个歌曲文件,然后 逐个转换
执行:
             $ find -type f -size -100000k -name '*.ape' | sed -e 's/\.ape$//' | xargs -I @ ffmpeg -i @.ape -acodec alac @.m4a
加强版(歌曲名里有空格(It's True.ape))
             $  find -type f -size -100000k -name '*.ape' -print0 | sed -e 's/\.ape//g'| xargs -0 -I @ ffmpeg -i @.ape -acodec alac @.m4a
最后删除原先的单个ape
             $ find -type f -size -100000k -name '*.ape' -print0 | xargs -0 rm