博文

HTS 语音合成方法 简述(2012-02-23 16:28:00)

摘要:这里,想要写一些关于HTS语音合成系统的东西。其实也就是想说说HTS语音合成系统是个啥玩意,它的基本思想和基本流程是什么?而不是用一个什么简图了事的那种。 总的来说,HTS语音合成系统,和HTK语音识别系统思想和流程基本相同,为什么这么说?那么我们就从流程上来说一条条分析。 1. 训练模型。两者都需要对语音基本单元(音素,半音节,音节)进行训练HMM模型。且训练模型使用的参数也是那些语音的acoustic参数,如MFCC, LSF, F0等。 2. 模型细化。 以音素模型为例,一般我们喜欢用di-phone 或 tri-phone来表征上下文相关的模型。但是这意味着对训练数据量的需求就更大,这时,我们一般需要做一些特殊处理,如状态绑定,对那些数据稀疏的状态,将他绑定在其他和它相似的状态上。对HTS, 可能采用基本分类树的方法来克服数据稀疏的问题。 3. 解码过程。在解码阶段,HTS语音合成和HTK语音识别刚好是一对可逆的过程。 在HTK语音识别中,给定的是每个音素的HMM模型和观察序列(如MFCC, F0序列,从输入语音中提取出来的),要求的是这些观察序列属于哪个模型。  而在HTS语音合成中,给定的是每个音素的HMM模型,以及由这些模型解码的结果(即输入的文本信息,经过处理后的音素序列),要求的是观察序列(这里得到的观察序列是指每一帧的MFCC,F0等特征)。   至此,HTK语音识别的过程就完成了。但是,HTS语音合成系统还有一个过程,那就是语音合成器。 所谓语音合成器,就是给定MFCC和F0特征,产生实际的语音数据。 这里,我们一般根据人的发音方式,即根据假设人的发生是通过一个声波(由声带振动产生), 经过声带共振(相当于一个滤波器),然后到达口鼻辐射出去。 这里,这个声波的产生过程是,对于浊音,用一个周期脉冲(其频率就是前面得到的F0)代替,对于清音,则用一个高斯白噪声代替。 而声带共振调制过程,这个滤波器的主要参数就是前面得到的MFCC参数。最后,经过一个辐射模型就可以得到所要的合成语音了。   可见,HTS语音合成的方法是严重的依赖于HTK的。所以,欲练此功,必先学习HTK。 此外,如果你已经掌握了HTK,那么,我觉得在这整个过程中,还有几个问题需要注意及好好解决。 (1) 对基频F0的建模。 因为对于......

阅读全文(7482) | 评论:3

音高于基频(2011-11-23 09:22:00)

摘要:  音高(Pitch)和基频(F0)是两个非常接近的概念,
尽管它们有所不同,但通常并不区分。   音高和基频的关系最早在音乐界被发现,
通常认为,音高增高八度音程相当于基频翻倍。 在1000Hz以下,基频翻倍略小于音高的八度音程;
而在1000-5000Hz范围,基频翻倍略大于音高的八度音程。
John M. Eargle. Music, Sound and Technology. Van Nostrand Reinhold, Toronto, 1995.
Stephen Handel. Listening. MIT Press, Cambridge, 1989.   在3000Hz以上,保持基频不变,音强增强能使得音高增加;
在2000Hz以下,保持基频不变,音强增强却使得音高降低。
Stanley Coren, Lawrence M. Ward, and James T. Enns. Sensation and Perception.
Harcourt Brace College Publishers, Toronto, 1994.   以上是来自于正弦波实验的结论,而实际上,人声的谐波结构也会影响音高感知。 目前的基频提取算法很多,但是并没有一个基频提取算法在各种条件下都工作得很好。
通常一个算法离开了特定领域,性能就会变差。提取音乐基频和语音基频的算法就有所差异。 ......

阅读全文(2802) | 评论:0

CRF++详解(二)(2011-11-18 16:57:00)

摘要:如果你只是想要简单的如何使用CRF++, 建议阅读  http://blog.csdn.net/Felomeng/article/details/4288492 。 这里以一个具体的例子介绍CRF++的一些思想和代码的实现过程。就加入我们想利用CRF++来进行分词。 一. 数据及其格式介绍 Train.data 中 F1 B-NP
华 F2 I-NP
人 F3 B-NP
民 F4 I-NP
共 F5 B-NP
和 F6 M-NP
国 F7 I-NP
国 F8 B-NP
家 F9 I-NP
主 F10 B-NP
席 F11 I-NP   Template: # Unigram
U00:%x[-2,0]
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U04:%x[2,0]
U05:%x[-1,0]/%x[0,0]
U06:%x[0,0]/%x[1,0] U12:%x[0,1] # Bigram
B 根据给定的template 和训练数据,需要得到一个CRF模型。 这里先对数据进行一个简单的介绍, Train.data: 中 F1 B-NP
华 F2 I-NP
人 F3 B-NP
对于输入的一句话,最基本的单元是一个个的字。所以我们处理的单元是字。我们的任务是判断每个字到底是词首,词中还是词尾。 在训练数据中,我们用B-NP, M_NP, I_NP分别表示词首,词中,词尾。  训练数据的最后一列表示训练集中每个字属于哪一类。 而F1, F2, F3..... 则是表示每个字的其他特征,比如词性,频率等。为了方便,这里假设这一列是词性列。你可以为它任意添加新的特征,这也是CRF的优势之一。但是一般来说,你如果在训练集中定义了新特征,那么你在 t......

阅读全文(13361) | 评论:1

CRF++详解(2011-11-18 15:39:00)

摘要:最近想利用条件随机场做一些实验。理论基础知识花了我一个星期时间。然后下载了CRF++的代码看看,又花了差不多一个星期。总算是把算法描述的东西和程序里的描述对应起来。 但是,这次学习的过程给我最大的感受就是网上关于这方面的知识还是偏少,尤其是关于CRF++代码的解释就更少了。由于CRF++本身的代码没有任何的注释,而很多函数动辄十几个参数,刚开始连参数代表什么意思,对应到算法描述中的什么变量都不知道。 这里,为了给这次学习过程一个总结,也为了给后面学习CRF,特别是使用CRF++代码的朋友们一个方便。 本文分两部分来描述,第一部分介绍算法原理,这里介绍的原理就是CRF++中用到的算法。 第二部分就是分析CRF++代码,介绍如何通过代码来实现这些算法。   一。 CRF原理 1.无约束最优化
  对无约束最优化不熟悉的读者也许要问,什么是无约束最优化。这里以一个例子来说明该问题。
  
  上图所示为一元函数f(x)的图像,无约束最优化问题,即不对定义域或值域做任何限制的情况下,求解函数f(x)的最小值,上面显示两个最小值点:一个为全局最小值点,另一个为局部最小值点。受限于算法复杂度等问题,目前大部分无约束最优化算法只能保证求取局部最小值点。这时读者不免要问,既然只能求取局部最小值点,那为什么这类算法还能应用呢。这是因为实际应用中,许多情形被抽象为函数形式后均为凸函数,对于凸函数来说局部最小值点即为全局最小值点,因此只要能求得这类函数的一个最小值点,该点一定为全局最小值点。
  理解了上面的无约束最优化问题之后,我们就可以开始介绍无约束最优化的求解过程了,对于无约束最优化的求解首先我们需要选择一个初始点x_0,如下所示:
  
  初始点选择好之后,就可以按照各种不同的无约束最优化求解算法,求解最小值点了。求解过程中主要涉及两个概念,即从初始点开始沿“哪个方向”以及“走多远”到达下一个点处。所谓“走多远”即之前提的“步长”的概念,“哪个方向”即方向概念。   2.Line Search
  Line search主要用于解决之前提到的步长的概念,即方向确定好之后,需要确定从当前点x_k沿着该方向走多远,以便走到下一个合适的点x_k+1。若......

阅读全文(18196) | 评论:0

拟牛顿法及其相关解法(2011-11-15 11:41:00)

摘要:最近在看条件随机场中的优化算法。其中就设计到了无约束化的最优化方法,也就是牛顿法。 在CRF(conditional random field)中,使用的是L-BFGS法。费了好大的劲把算法的原理及推导算是看明白了,可是到了具体实现上,又碰到问题了,比如在求搜索方向的时候,使用       但是程序中如何实现呢?   现在转载一篇文章,看过之后,会非常受益。 使用导数的最优化算法中,拟牛顿法是目前为止最为行之有效的一种算法,具有收敛速度快、算法稳定性强、编写程序容易等优点。在现今的大型计算程序中有着广泛的应用。本文试图介绍拟牛顿法的基础理论和若干进展。 牛顿法 (Newton Method) 牛顿法的基本思想是在极小点附近通过对目标函数做二阶Taylor展开,进而找到的极小点的估计值[1]。一维情况下,也即令函数为 则其导数满足 因此        (1) 将作为极小点的一个进一步的估计值。重复上述过程,可以产生一系列的极小点估值集合。一定条件下,这个极小点序列收敛于的极值点。 将上述讨论扩展到维空间,类似的,对于维函数有 其中和分别是目标函数的的一阶和二阶导数,表现为维向量和 矩阵,而后者又称为目标函数在处的Hesse矩阵。 设可逆,则可得与方程(1)类似的迭代公式:      (2) 这就是原始牛顿法的迭代公式。 原始牛顿法虽然具有二次终止性(即用于二次凸函数时,经有限次迭代必达极小点),但是要求初始点需要尽量靠近极小点,否则有可能不收敛。因此人们又提出了阻尼牛顿法[1]。这种方法在算法形式上等同于所有流行的优化方法,即确定搜索方向,再沿此方向进行一维搜索,找出该方向上的极小点,然后在该点处重新确定搜索方向,重复上述过程,直至函数梯度小于预设判据。具体步骤列为算法1。
  算法1: (1)  给定初始点,设定收敛判据,. (2)  计算和. (3)  若 < ,则停止迭代,否则确定搜索方向. (4)  从出发,沿做一维搜索, 令. (5)  设,转步......

阅读全文(14292) | 评论:0

const 用法大全(2010-11-04 10:30:00)

摘要:哎,今天又要普及基本知识了。可是这个const的用法确实是很多C/C++程序员很容易混淆的东西。今天好好整理一番,以供大家参考。 const主要是为了程序的健壮型,减少程序出错.
最基本的用法:
const int a=100; b的内容不变,b只能是100也就是声明一个int类型的常量(#define b =100)
int const b=100; //和上面作用一样 

const指针和引用一般用在函数的参数中
int* m = &a; //出错,常量只能用常指针
int c= 1;const int*pc = &c;//常指针可指向常量 

const int* pa = &a; //指针指向的内容为常量(就是b的值不变)
int const *a = &b; //指针指向的内容为常量(就是b的值不变)*p=3//error
int* const a = &b; //指针为常量,不能更改指针了如 a++但可以改值*p=3; 

从这可以看出const放在*左侧修饰的是指针的内容,const放在*右侧修饰的是指针
本身. 

const引用的用法和指针一样
int const & a=b; 和指针一样
const int& a=b; 和指针一样
但没有 int& const a=b 的用法因为引用不能做移位运算,但只是出个warning 

const int* const a = &b; //综合应用,一般用来传递多维的数组
类如:char* init[] = {"Paris","in the","Spring"};
void fun(const int* const a){}
fun(init)//保护参数不被修改 

int A(int)const; /......

阅读全文(2062) | 评论:0

C语言中的位运算(2010-11-03 15:42:00)

摘要:在此特别声明,此文转载至http://www.cnblogs.com/911/archive/2008/05/20/1203477.html。 如果您此前参考过这篇文章了,那么这里道歉,害您又一次进入。   不过,之后,我将再写一篇关于16进制一起其他进制的数据如何直接进行位运算,以作补偿。   位运算是指按二进制进行的运算。在系统软件中,常常需要处理二进制位的问题。C语言提供了6个位操作运算符。这些运算符只能用于整型操作数,即只能用于带符号或无符号的char,short,int与long类型。
C语言提供的位运算符列表:
运算符 含义 描述
& 按位与 如果两个相应的二进制位都为1,则该位的结果值为1,否则为0
| 按位或 两个相应的二进制位中只要有一个为1,该位的结果值为1
^ 按位异或 若参加运算的两个二进制位值相同则为0,否则为1
~ 取反 ~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1变0
<< 左移 用来将一个数的各二进制位全部左移N位,右补0
>> 右移 将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数,高位补0 1、“按位与”运算符(&)     按位与是指:参加运算的两个数据,按二进制位进行“与”运算。如果两个相应的二进制位都为1, 则该位的结果值为1;否则为0。这里的1可以理解为逻辑中的true,0可以理解为逻辑中的false。按位与其 实与逻辑上“与”的运算规则一致。逻辑上的“与”,要求运算数全真,结果才为真。若, A=true,B=true,则A∩B=true 例如:3&5 3的二进制编码是11(2)。(为了区分十进制和其他进制,本文规 定,凡是非十进制的数据均在数据后面加上括号,括号中注明其进制,二进制则标记为2)内存储存数据 的基本单位是字节(Byte),一个字节由8个位(bit)所组成。位是用以描述电脑数据量的最小单位。二 进制系统中,每......

阅读全文(3313) | 评论:1

C语言下求每种变量类型的最大值(2010-10-29 17:44:00)

摘要:以前总是需要人工的写上如果某个short型数据是否大于 32767。总是觉得程序很难看,每次需要输入数字总是很烦。 下面介绍一种求每种变量类型的最大数值和最小数值的简便方法。 假如是要求 int 型的最大值和最小值,可以按照如下求。 unsigned int a; int b; a = (unsigned int) -1; //获得unsigned int 的最大值,最小值为0 b = ((unsigned int)-1) >>1;  //获得 int 的最大值 b = ~(((unsigned int)-1) >>1); //获得int的最小值    其他类型也是类推  ......

阅读全文(3017) | 评论:0

C2059和C2733同时出现的错误解决(2010-07-27 13:44:00)

摘要:症状   在 Microsoft Visual Studio 2005 中创建一个 c + + 应用程序。 您定义 _CRTDBG_MAP_ALLOC,然后编译的时候会出现 C2059和C2733的错误。 loadTOCNode(1, 'symptoms');   例如对于假定 c + + 应用程序中包含下面的代码 #define _CRTDBG_MAP_ALLOC #include <malloc.h> #include <crtdbg.h> #include <stdlib.h> 在此的示例编译 c + + 应用程序时您会收到以下编译器错误消息: 错误 C2059: 语法错误: 常量 错误 C2733: 第二个重载函数 _dupenv_s_dbg 不允许使用的 C 链接 解决方法 要变通解决此问题,请按照下列步骤操作: 启动 Visual Studio 2005。 在 文件 菜单上指向 打开,然后单击 项目/解决方案。 找到该项目或您要打... loadTOCNode(1, 'workaround'); 要变通解决此问题,请按照下列步骤操作: 启动 Visual Studio 2005。 在 文件 菜单上指向 打开,然后单击 项目/解决方案。 找到该项目或您要打开,该解决方案,然后单击 打开。 复制并粘贴以下代码在代码窗口中。下面代码应该黏贴在 # include <stdlib.h> 语句 前。 #pragma push_macro("_dupenv_s") #pragma push_macro("_wdupenv_s") #undef _dupenv_s #undef _wdupenv_s 复制并粘贴以下代码在代码窗口中。该代码应粘贴在 # include <stdlib.h> 语句  之后。 #pragma pop_macro("_dupe......

阅读全文(3541) | 评论:0

SHFILEOPSTRUCT 文件夹操作 困惑(2010-03-10 09:24:00)

摘要:相信对文件夹操作是大家都会经常碰到的问题。而在文件夹操作中,利用 SHFILEOPSTRUCT 进行操作是最快最方便的,而Windows本身自己也用这个进行文件夹的操作,如移动,复制,粘帖等操作。 而最近我在用SHFILEOPSTRUCT进行文件夹移动的时候,却发现它有好几个需要注意的问题。 首先,给出MSDN以及大部分网上会给出的示例代码:            SHFILEOPSTRUCT   sfo;           sfo.hwnd   =   NULL;  
          sfo.wFunc   =   FO_MOVE;  
          sfo.pFrom   =   "D:\\1";  
          sfo.pTo   =   "D:\\2";  
          sfo.fFlags   =   FOF_SILENT   |   FOF_NOCONFIRMATION   |   FOF_NOCONFIRMMKDIR;  
          hr ......

阅读全文(5092) | 评论:0