码迷,mamicode.com
首页 > 其他好文 > 详细

[从头学声学] 第209节 双音节声音

时间:2016-05-12 14:52:49      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:

剧情提要:
[机器小伟]在[工程师阿伟]的陪同下进行着声学神通的修炼。
这次要研究的是[双音节声音]。

正剧开始:

星历2016年05月10日 11:54:28, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[双音节声音]。


要研究双音节,就先要有单音节,所以小伟整理了一些音符:


音节库:音节名


音节库:音节数据


有了这些原始的数据,看能搭配出些什么来吧。


idleWave = [b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00', b'\x00'];

#把十进制数按照小尾字节序切割
def littleEndian(number, byte = 4):
    result = [0]*byte;

    for i in range(byte):
        result[i] = number%256;
        number//=256;
    return result;

###
# @usage   写.wav文件,能把声波数据阵列用二进制写成.wav。
# @author  mw
# @date    2016年04月28日  星期四  14:31:34 
# @param
# @return
#
###
def writeWav(index):
    
    byteArray = [];
    dataArray = [];

 
    #样本数据阵列
    sampleArray = [];


    sampleArray = waveDataGen();

    #样本数据点数
    N = len(sampleArray);
    times = 1;
    dataSize = N*times;
    
    fileSize = dataSize+44; #44为格式头部分所用字节数
    
    #RIFF WAVE CHUNK
    RIFF_ID = [0x52, 0x49, 0x46, 0x46];  #'RIFF'
    RIFF_Size = littleEndian(fileSize-8, 4); #文件总字节数减去8
    RIFF_Type = [0x57, 0x41,0x56, 0x45, 0x66, 0x6D, 0x74, 0x20]; #'WAVEfat '

    #Format Chunk
    Format_10_17 = [0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00];#过滤4+格式2+声道2=8个字节
    Format_18_1B = [0x11, 0x2B, 0x00, 0x00]; #采样频率0x2B11 = 11025
    Format_1C_1F = [0x22, 0x56, 0x00, 0x00]; #比持率 = 频率*通道*样本位 = 22050
    Format_20_23 = [0x02, 0x00, 0x10, 0x00]; #块对齐 = 通道数* 样本位数 = 1*2 = 2    

    #Fact Chunk(optional)

    #Data Chunk
    Data_24_27 = [0x64, 0x61, 0x74, 0x61]; #'DATA'标记
    Data_Size = littleEndian(fileSize-44, 4); #下面的Data部分的字节数,文件总字节数-44


    #RIFF WAVE CHUNK
    '''
    for i in range(4):
        byte = struct.pack('B', RIFF_ID[i]);
        byteArray.append(byte);
    '''

    RIFF = [b'R', b'I', b'F', b'F'];
    for i in range(4):
        byteArray.append(RIFF[i]);

    for i in range(4):
        byte = struct.pack('B', RIFF_Size[i]);
        byteArray.append(byte);

    '''
    for i in range(8):
        byte = struct.pack('B', RIFF_Type[i]);
        byteArray.append(byte);

    #Format Chunk
    for i in range(8):
        byte = struct.pack('B', Format_10_17[i]);
        byteArray.append(byte);

    for i in range(4):
        byte = struct.pack('B', Format_18_1B[i]);
        byteArray.append(byte);

    for i in range(4):
        byte = struct.pack('B', Format_1C_1F[i]);
        byteArray.append(byte);

    for i in range(4):
        byte = struct.pack('B', Format_20_23[i]);
        byteArray.append(byte);

    
    #Data Chunk
    for i in range(4):
        byte = struct.pack('B', Data_24_27[i]);
        byteArray.append(byte);
    '''

    #Format_28_2B是数据块大小,formatHead是它前面的所有部分
    formatHead = [b'W', b'A', b'V', b'E', b'f', b'm', b't', b' ',                   b'\x10', b'\x00', b'\x00', b'\x00', b'\x01', b'\x00', b'\x01', b'\x00',                   b'\x11', b'+', b'\x00', b'\x00',                   b'"', b'V', b'\x00', b'\x00',                   b'\x02', b'\x00', b'\x10', b'\x00',                   b'd', b'a', b't', b'a'];

    for i in range(len(formatHead)):
        byteArray.append(formatHead[i]);

    for i in range(4):
        byte = struct.pack('B', Data_Size[i]);
        byteArray.append(byte);

    
    #写出到文件
    print('文件写入开始。>>>');

    s = 'randMusic'+str(index)+'.wav';
        
    fout= open(s, 'wb');
    size = len(byteArray);
    
    for i in range(size):
        fout.write(byteArray[i]);       
    
    size = len(sampleArray);
    sizeIdle = len(idleWave);    

    
    for j in range(times):
        for i in range(size):
            fout.write(sampleArray[i]);

    fout.close();
    print('文件写入完毕。');


#生成音乐文件内容
def waveDataGen():
    import wavename;
    import wavedata;

    vowelName_en = wavename.vowelName_en;
    size_ve = len(vowelName_en);
    vowelName_zh = wavename.vowelName_zh;
    size_vz = len(vowelName_zh);
    consonantName_zh = wavename.consonantName_zh;
    size_cz = len(consonantName_zh);
    musicToneName = wavename.musicToneName;
    size_mt = len(musicToneName);

    #print(size_ve, size_vz, size_cz, size_mt);
    #16 29 70 77

    #22k/s => 1.32M/min => 15.84M/12min
    data = [];

    for i in range(size_vz):
        voicePiece_1 = eval('wavedata.'+vowelName_zh[i]);
        
        for j in range(size_vz):
            if i == j:
                continue;
            
            voicePiece_2 = eval('wavedata.'+vowelName_zh[j]);
            
            for k in range(3):                
                data += voicePiece_1;

            for k in range(7):
                data += voicePiece_2;

            for k in range(30):
                data += idleWave;

    for i in range(100):
        data += idleWave;

    return data;

if __name__ == '__main__':
    writeWav(8);

上面这段是搭配元音的,效果是这个:

元音双音节

点击打开链接-- 元音双音节


接着试一下:

单音配元音

点击打开链接--单音配元音


继续试:

乐音配元音

点击打开链接--乐音配元音


这些音乐段的时长都很长,因为配对比较多。

但是声音还是没达到小伟需要的效果。


#生成音乐文件内容
def waveDataGen():
    import wavename;
    import wavedata;

    vowelName_en = wavename.vowelName_en;
    size_ve = len(vowelName_en);
    vowelName_zh = wavename.vowelName_zh;
    size_vz = len(vowelName_zh);
    consonantName_zh = wavename.consonantName_zh;
    size_cz = len(consonantName_zh);
    musicToneName = wavename.musicToneName;
    size_mt = len(musicToneName);

    #print(size_ve, size_vz, size_cz, size_mt);
    #16 29 70 77

    #22k/s => 1.32M/min => 15.84M/12min
    data = [];

    for i in range(size_mt):
        voicePiece_1 = eval('wavedata.'+musicToneName[i]);
        
        for j in range(size_vz):
            voicePiece_2 = eval('wavedata.'+vowelName_zh[j]);
            
            for k in range(3):                
                data += voicePiece_1;

            for k in range(7):
                data += voicePiece_2;

            for k in range(30):
                data += idleWave;

    for i in range(100):
        data += idleWave;

    return data;

本节到此结束,欲知后事如何,请看下回分解。

[从头学声学] 第209节 双音节声音

标签:

原文地址:http://blog.csdn.net/mwsister/article/details/51361994

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!