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

[从头学声学] 第206节 发声学数据

时间:2016-05-06 15:17:43      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:

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

正剧开始:


星历2016年05月05日 10:58:13, 银河系厄尔斯星球中华帝国江南行省。
[工程师阿伟]正在和[机器小伟]一起研究[发声学数据]。


英文国际音标:

技术分享


技术分享


汉语拼音音标: 

技术分享

技术分享

技术分享

技术分享





技术分享
技术分享
技术分享
技术分享
技术分享
技术分享
技术分享
技术分享
技术分享

为什么有些音高中低音无法混起来呢,感觉各干各的。

技术分享
技术分享

这是能混起来的
技术分享
技术分享

差别在哪呢?小伟暂时想不明白,看来要系统地去学一下知识了。

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;




    

#把UltraEdit中的值字串转化为hex序列组
def hexExpr(string):
    resultString = '';
    size = len(string);
    for i in range(size):
        if (i == 0 ):
            resultString += '0x'+string[i];
        elif (string[i] == ' '):
            resultString += ', 0x';
        else:
            resultString += string[i];
    print(resultString);


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

    #样本数据点数
    N = len(sampleArray);
    times = 2;
    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('文件写入开始。>>>');
    fout= open(filename[index]+'.wav', '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 sampleGen(N, freq1, freq2, freq3):
    #设立20000个数值点,约可听2秒
    sampleArray = [];

    coef = 2*math.pi/11025;

    coef1 = coef*freq1;
    coef2 = coef*freq2;
    coef3 = coef*freq3;
    

    for i in range(N):
        value = (math.sin(i*coef1) + math.sin(i*coef2) + math.sin(i*coef3))/3;
        if (value < 0):
            value *= 32768;
        else:
            value *= 32767;
        sampleArray.append(round(value));
    return sampleArray;


def waveDataGen(freq1, freq2, freq3):
    N = 200;

    sampleArray = sampleGen(N, freq1, freq2, freq3);
    dataArray = [];
    
    for i in range(N):
        value = littleEndian(sampleArray[i], 2);
        for j in range(2):
            byte = struct.pack('B', value[j]);
            dataArray.append(byte);    

    return dataArray;

def genIdle():
    dataArray = [];
    
    for i in range(200):
        value = littleEndian(0, 2);
        for j in range(2):
            byte = struct.pack('B', value[j]);
            dataArray.append(byte);    

    print(dataArray);

#波形选择
def waveDataChoose(index, filename):
    import wavedata;
    
    tmpdata = eval('wavedata.'+filename[index]);

    sampledata = [];

    for i in range(1, 21):
        for j in range(15):
            sampledata += idleWave;

        for j in range(i):
            sampledata += tmpdata;

        for j in range(15):
            sampledata += idleWave;

    return sampledata; 
    

#调用入口, 生成wav文件
def tmp(filename):
    size = len(filename);
    
    for i in range(250, 300):
        if i > 300:
            break;
        
        writeWav(i, filename);

#生成声波数据
def tmp2():
    print('生成波形开始。>>>');
    
    fout= open('output.txt', 'w');
    
    i, k = 200, 1600;
    for j in range(551, 1001, 1):
        dataStr = 'combineWave_'+str(i)+'_'+str(j)+'_'+str(k) + ' = [';
        fout.write(dataStr);

        data = waveDataGen(i, j, k);
        size = len(data);

        for n in range(size):
            fout.write(str(data[n]));
            if (n < size-1):
                fout.write(', ');

        fout.write('];');
            
        fout.write('\r\n');

    fout.close();
    print('生成波形结束,请到output.txt查收。');



#打印文件名             
def tmp3():
    filename = [];
    
    i, k = 200, 1600;
    for j in range(500, 1001, 1):
        dataStr = 'combineWave_'+str(i)+'_'+str(j)+'_'+str(k);
        filename.append(dataStr);

    print(filename);


if __name__ == '__main__':
    import wavename;
    filename = wavename.wavename;
    
    part = 1;

    if (part == 3):
        tmp3();
    elif (part == 2):
        tmp2();
    elif (part == 1):
        tmp(filename);
        


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

[从头学声学] 第206节 发声学数据

标签:

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

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