您的位置:首页 > 其它

[从头学声学] 第207节 声学的原理

2016-05-06 14:22 525 查看
剧情提要:

[机器小伟]在[工程师阿伟]的陪同下进行着声学神通的修炼。

这次要研究的是[声学的原理]。

正剧开始:

星历2016年05月06日 13:54:48, 银河系厄尔斯星球中华帝国江南行省。

[工程师阿伟]正在和[机器小伟]一起研究[声学的原理]。















这个音高频率表是这样算出来的:

[32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55.0, 58.27, 61.735, 65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110.0, 116.541, 123.471, 130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220.0, 233.082, 246.942, 261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440.0, 466.164, 493.883, 523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880.0, 932.328, 987.767, 1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760.0, 1864.655, 1975.533, 2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520.0, 3729.31, 3951.066]

def tmp():
#公比 半音
q = 2**(1/12);
#A4 = (+9)
A4 = 440;
#C1 = (-36)
C1 = A4/q**45;

toneFrequence = [];
for i in range(-36, 48):
toneFrequence.append(round(A4*q**(i-9), 3));

print(toneFrequence);




>>> 203.91*5+90.22
1109.77
>>> 203.91*5+90.22*2
1199.99

>>>
[440, 469.865, 495.0, 528.598, 556.875, 594.672, 626.484, 669.006, 704.795, 752.632, 792.894, 846.711, 892.006]

#三分损益法(黄钟大吕音)
def tmp():
#公比 半音
q = 2**(1/1200);
#A4 = (+9)
A4 = 440;
tmpfreq  = A4;

toneFrequence = [];
for i in range(13):
toneFrequence.append(round(tmpfreq, 3));
if (i%2==0):
tmpfreq *= q**(113.69);
else:
tmpfreq *= q**(90.22);
print(toneFrequence);


















































































阿伟给小伟做了一个乐音遍历工具,可以听出国际谱中的所有音符。

本来可以传到酷狗的,但想了想,还是传优酷了,尽管很短,

还要看很长时间的广告。

点击打开链接 -- 乐音音符

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 = [];

mode = 2;

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

if mode == 1:
sampleArray = waveDataChoose(index, filename);
elif mode == 2:
sampleArray = waveDataChoose_2(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('文件写入开始。>>>');

s = '';
if mode == 1:
s = filename[index]+'.wav';
elif mode == 2:
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 sampleGen(N, freq):
#设立20000个数值点,约可听2秒
sampleArray = [];

coef = 2*math.pi*freq/11025;
#音色调节
weight = [1, 2.55, 2.13, 1.98, 1.57, 1.23];
total = sum(weight);

for i in range(N):
xvalue = coef*i;

yvalue = (weight[0]*math.sin(xvalue) + weight[1]*math.sin(xvalue*2)+ weight[2]*math.sin(xvalue*3) +\
weight[3]*math.sin(xvalue*4) + weight[4]*math.sin(xvalue*5)+ weight[5]*math.sin(xvalue*6))/total;
if (yvalue < 0):
yvalue *= 32768;
else:
yvalue *= 32767;
sampleArray.append(round(yvalue));
return sampleArray;

def waveDataGen(freq):
N = 200;

sampleArray = sampleGen(N, freq);
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;

def waveDataChoose_2(filename):
import wavedata;

size = len(filename);

sampledata = [];

for i in range(300):
#index_1 = random.randint(24, size-1-36);
idleCircle = random.randint(2, 8);
longIdleCircle = random.randint(8, 20);
musicCircle = random.randint(2, 15);

tmpdata = eval('wavedata.'+filename[i%size]);

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

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

if (i%longIdleCircle == 0):
for j in range(longIdleCircle):
sampledata += idleWave;

for i in range(30):
sampledata += idleWave;

return sampledata;

#调用入口, 生成wav文件
def tmp(filename):
size = len(filename);

for i in range(size):
if i > 300:
break;

writeWav(i, filename);

def tmp_2(index, filename):
writeWav(index, filename);

#生成声波数据
def tmp2():
print('生成波形开始。>>>');

fout= open('output.txt', 'w');

frequence = [32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55.0, 58.27, 61.735, \
65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110.0, 116.541, 123.471, \
130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220.0, 233.082, 246.942, \
261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440.0, 466.164, 493.883, \
523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880.0, 932.328, 987.767, \
1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760.0, 1864.655, 1975.533, \
2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520.0, 3729.31, 3951.066];

size = len(frequence);

for i in range(size):
dataStr = 'musicfreq_'+str(frequence[i]).replace('.', 'p') + ' = [';
fout.write(dataStr);

data = waveDataGen(frequence[i]);
size_1 = len(data);

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

fout.write('];');

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

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

#打印文件名
def tmp3():
filename = [];

frequence = [32.703, 34.648, 36.708, 38.891, 41.203, 43.654, 46.249, 48.999, 51.913, 55.0, 58.27, 61.735, \
65.406, 69.296, 73.416, 77.782, 82.407, 87.307, 92.499, 97.999, 103.826, 110.0, 116.541, 123.471, \
130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220.0, 233.082, 246.942, \
261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440.0, 466.164, 493.883, \
523.251, 554.365, 587.33, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880.0, 932.328, 987.767, \
1046.502, 1108.731, 1174.659, 1244.508, 1318.51, 1396.913, 1479.978, 1567.982, 1661.219, 1760.0, 1864.655, 1975.533, \
2093.005, 2217.461, 2349.318, 2489.016, 2637.02, 2793.826, 2959.955, 3135.963, 3322.438, 3520.0, 3729.31, 3951.066];

size = len(frequence);

for i in range(size):
dataStr = 'musicfreq_'+str(frequence[i]).replace('.', 'p');
filename.append(dataStr);

print(filename);

if __name__ == '__main__':
part = 1;

if (part == 3):
tmp3();
elif (part == 2):
tmp2();
elif (part == 1):
import wavename;
filename = wavename.wavename;

tmp_2(3, filename);






点击打开链接 -- 元音发音

#生成声音样本,返回样本矩阵
def sampleGen_2(N, freq1, freq2):
#设立20000个数值点,约可听2秒
sampleArray = [];

coef = 2*math.pi/11025;

#音色调节
weight = [1.53, 1];
total = sum(weight);

for i in range(N):
xcoef_1 = coef*i*freq1;
xcoef_2 = coef*i*freq2;

yvalue = (weight[0]*math.sin(xcoef_1)+ weight[1]*math.sin(xcoef_2))/total;

if (yvalue < 0):
yvalue *= 32768;
else:
yvalue *= 32767;
sampleArray.append(round(yvalue));
return sampleArray;

def waveDataGen_2(freq1, freq2):
N = 200;

sampleArray = sampleGen_2(N, freq1, freq2);
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 tmp2_2():
print('生成波形开始。>>>');

fout= open('output.txt', 'w');

frequence = [[240,2400],
[235,2100],
[390,2300],
[370,1900],
[610,1900],
[585,1710],
[850, 1610],
[820, 1530],
[750, 940],
[700, 760],
[600, 1170],
[500, 700],
[460, 1310],
[360, 640],
[300, 1390],
[250, 595]];

size = len(frequence);

for i in range(size):
dataStr = 'primaryTone_'+ str(frequence[i][0])+'_'+str(frequence[i][1]) + ' = [';

fout.write(dataStr);

data = waveDataGen_2(frequence[i][0], frequence[i][1]);
size_1 = len(data);

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

fout.write('];');

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

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

#生成声波数据
def tmp3_2():
filename = [];

frequence = [[240,2400],
[235,2100],
[390,2300],
[370,1900],
[610,1900],
[585,1710],
[850, 1610],
[820, 1530],
[750, 940],
[700, 760],
[600, 1170],
[500, 700],
[460, 1310],
[360, 640],
[300, 1390],
[250, 595]];

size = len(frequence);

for i in range(size):
dataStr = 'primaryTone_'+ str(frequence[i][0])+'_'+str(frequence[i][1]);
filename.append(dataStr);

print(filename);

if __name__ == '__main__':
part = 1;

if (part == 3):
tmp3_2();
elif (part == 2):
tmp2_2();
elif (part == 1):
import wavename;
filename = wavename.wavename;

tmp_2(5, filename);




















































































本节到此结束,欲知后事如何,请看下回分解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: