使用 numpy 和 scipy 生成波形文件后波形之间的间隙
Gaps in between waveforms after generating wave file using numpy and scipy
我使用 python 3.7、numpy 和 scipy 编写了一个程序,该程序使用 pi 的数字生成波形,并将它们拼接在一起形成 "song"。我唯一的问题是每个音符之间有空隙。
我尝试过使用数学函数让每个音符的波浪淡出,我尝试让音符重叠一点(运气不太好),还有一些更疯狂的事情没有做任何事...
import numpy as np
from scipy.io.wavfile import write
pi = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848"
piarray = list(pi)
piarray.remove(".")
print(piarray)
# Samples per second
sps = 44100
# Frequency / pitch of the sine wave
freq_hz = 440.0
# Duration
duration_s = 0.2
each_sample_number = np.arange(duration_s * sps)
for i in range(len(piarray)):
if(piarray[i] == "0"):
freq_hz = 277.18
elif(piarray[i] == "1"):
freq_hz = 311.13
elif(piarray[i] == "2"):
freq_hz = 369.99
elif(piarray[i] == "3"):
freq_hz = 415.30
elif(piarray[i] == "4"):
freq_hz = 466.16
elif(piarray[i] == "5"):
freq_hz = 554.37
elif(piarray[i] == "6"):
freq_hz = 622.25
elif(piarray[i] == "7"):
freq_hz = 739.99
elif(piarray[i] == "8"):
freq_hz = 830.61
else:
freq_hz = 932.33
waveform = np.sin(2 * np.pi * each_sample_number * freq_hz / sps)*0.3
#The line above and below this one make an individual note.
waveform_integers = np.int16(waveform * 32767)
if(i == 0):
waveformc = waveform_integers
print(waveformc)
else:
waveformc = np.append(waveformc, waveform_integers, axis=None)
write('song.wav', sps, waveformc)
print("DONE")
我已经尝试寻找解决这个特定问题的方法,但我没有在任何地方找到任何相关的东西。我只是希望波形文件在每个音符之间没有间隙,但是有。感谢您能给我的任何帮助!
您的波形之间没有任何间隙。您可以从 Reaper 的结果视图中看到您有连续的声音:
每次开始一个新音符时,您的波形都会出现不连续性。每次音符更改时,都会听到咔哒声或爆裂声。由于每个音符的波形都是根据底层数据结构计算的,因此它们都将在 0 处有一个零交叉点,然后从那里快速相互脱离一个相位。
要解决此问题,您可以尝试对每个声音进行适当的渐变 in/out,或者确保跟踪波形的相位并在音符变化时保持一致。
对于衰减函数,您需要类似于 (frames - each_sample_number) / frames)**n
的东西,以便它在最后达到零。您可以试用此功能,看看它如何影响声音的持续时间和音符之间的感知削波。
import numpy as np
from scipy.io.wavfile import write
pi = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848"
piarray = list(pi)
piarray.remove(".")
print(piarray)
# Samples per second
sps = 44100
# Frequency / pitch of the sine wave
freq_hz = 440.0
# Duration
duration_s = 0.2
frames = duration_s * sps # counting how many frames for a note
each_sample_number = np.arange(duration_s * sps)
for i in range(len(piarray)):
if(piarray[i] == "0"):
freq_hz = 277.18
elif(piarray[i] == "1"):
freq_hz = 311.13
elif(piarray[i] == "2"):
freq_hz = 369.99
elif(piarray[i] == "3"):
freq_hz = 415.30
elif(piarray[i] == "4"):
freq_hz = 466.16
elif(piarray[i] == "5"):
freq_hz = 554.37
elif(piarray[i] == "6"):
freq_hz = 622.25
elif(piarray[i] == "7"):
freq_hz = 739.99
elif(piarray[i] == "8"):
freq_hz = 830.61
else:
freq_hz = 932.33
# added fall off feature
waveform = (((frames - each_sample_number) / frames)**0.5) * np.sin(
np.pi+ 2 * np.pi * each_sample_number * freq_hz / sps)*0.3
#The line above and below this one make an individual note.
waveform_integers = np.int16(waveform * 32767)
if(i == 0):
waveformc = waveform_integers
print(waveformc)
else:
waveformc = np.append(waveformc, waveform_integers, axis=None)
write('song.wav', sps, waveformc)
print("DONE")
可以在波形上看到当前设置的结果:
我在频率中添加了一个 "correction factor" 以确保每个波都以零振幅结束,并且不会有间断。它会稍微改变频率,但不会超过 1%。我就是这样做的:
cor_fac = round(each_sample_number[-1] * freq_hz / sps)/(each_sample_number[-1] * freq_hz / sps)
cor_factors.append(cor_fac)
waveform = np.sin(2 * np.pi * each_sample_number * freq_hz / sps * cor_fac)*0.3
我认为它解决了问题。
如果频率上的变化不可接受,您可以尝试更改样本阵列的开始,使其以与最后一个波形完成时相同的幅度开始。
我会尽力做到,post 在这里。
让我知道它对你有用。
编辑:
不改变声音频率的代码:
import numpy as np
from scipy.io.wavfile import write
import matplotlib.pyplot as plt
import wave
import sys
pi = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848"
piarray = list(pi)
piarray.remove(".")
print(piarray)
# Samples per second
sps = 44100
# Frequency / pitch of the sine wave
freq_hz = 440.0
# Duration
duration_s = 0.2
last_amp = 0
cor_factors = []
direction_down = False
for i in range(len(piarray)):
if(piarray[i] == "0"):
freq_hz = 277.18
elif(piarray[i] == "1"):
freq_hz = 311.13
elif(piarray[i] == "2"):
freq_hz = 369.99
elif(piarray[i] == "3"):
freq_hz = 415.30
elif(piarray[i] == "4"):
freq_hz = 466.16
elif(piarray[i] == "5"):
freq_hz = 554.37
elif(piarray[i] == "6"):
freq_hz = 622.25
elif(piarray[i] == "7"):
freq_hz = 739.99
elif(piarray[i] == "8"):
freq_hz = 830.61
else:
freq_hz = 932.33
# cor_fac = round(each_sample_number[-1] * freq_hz / sps)/(each_sample_number[-1] * freq_hz / sps)
# cor_factors.append(cor_fac)
start = np.arcsin(last_amp/0.3)
if direction_down:
start = np.pi - start
start = start/(2 * np.pi * freq_hz / sps)
each_sample_number = np.arange(start, start + duration_s * sps)
waveform = np.sin(2 * np.pi * each_sample_number * freq_hz / sps)*0.3
print(waveform[0]-last_amp)
last_amp = waveform[-1]
direction_down = waveform[-1]<waveform[-2]
#The line above and below this one make an individual note.
waveform_integers = np.int16(waveform * 32767)
if(i == 0):
waveformc = waveform_integers
print(waveformc)
else:
waveformc = np.append(waveformc, waveform_integers, axis=None)
write('song_2.wav', sps, waveformc)
print("DONE")
我使用 python 3.7、numpy 和 scipy 编写了一个程序,该程序使用 pi 的数字生成波形,并将它们拼接在一起形成 "song"。我唯一的问题是每个音符之间有空隙。
我尝试过使用数学函数让每个音符的波浪淡出,我尝试让音符重叠一点(运气不太好),还有一些更疯狂的事情没有做任何事...
import numpy as np
from scipy.io.wavfile import write
pi = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848"
piarray = list(pi)
piarray.remove(".")
print(piarray)
# Samples per second
sps = 44100
# Frequency / pitch of the sine wave
freq_hz = 440.0
# Duration
duration_s = 0.2
each_sample_number = np.arange(duration_s * sps)
for i in range(len(piarray)):
if(piarray[i] == "0"):
freq_hz = 277.18
elif(piarray[i] == "1"):
freq_hz = 311.13
elif(piarray[i] == "2"):
freq_hz = 369.99
elif(piarray[i] == "3"):
freq_hz = 415.30
elif(piarray[i] == "4"):
freq_hz = 466.16
elif(piarray[i] == "5"):
freq_hz = 554.37
elif(piarray[i] == "6"):
freq_hz = 622.25
elif(piarray[i] == "7"):
freq_hz = 739.99
elif(piarray[i] == "8"):
freq_hz = 830.61
else:
freq_hz = 932.33
waveform = np.sin(2 * np.pi * each_sample_number * freq_hz / sps)*0.3
#The line above and below this one make an individual note.
waveform_integers = np.int16(waveform * 32767)
if(i == 0):
waveformc = waveform_integers
print(waveformc)
else:
waveformc = np.append(waveformc, waveform_integers, axis=None)
write('song.wav', sps, waveformc)
print("DONE")
我已经尝试寻找解决这个特定问题的方法,但我没有在任何地方找到任何相关的东西。我只是希望波形文件在每个音符之间没有间隙,但是有。感谢您能给我的任何帮助!
您的波形之间没有任何间隙。您可以从 Reaper 的结果视图中看到您有连续的声音:
每次开始一个新音符时,您的波形都会出现不连续性。每次音符更改时,都会听到咔哒声或爆裂声。由于每个音符的波形都是根据底层数据结构计算的,因此它们都将在 0 处有一个零交叉点,然后从那里快速相互脱离一个相位。
要解决此问题,您可以尝试对每个声音进行适当的渐变 in/out,或者确保跟踪波形的相位并在音符变化时保持一致。
对于衰减函数,您需要类似于 (frames - each_sample_number) / frames)**n
的东西,以便它在最后达到零。您可以试用此功能,看看它如何影响声音的持续时间和音符之间的感知削波。
import numpy as np
from scipy.io.wavfile import write
pi = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848"
piarray = list(pi)
piarray.remove(".")
print(piarray)
# Samples per second
sps = 44100
# Frequency / pitch of the sine wave
freq_hz = 440.0
# Duration
duration_s = 0.2
frames = duration_s * sps # counting how many frames for a note
each_sample_number = np.arange(duration_s * sps)
for i in range(len(piarray)):
if(piarray[i] == "0"):
freq_hz = 277.18
elif(piarray[i] == "1"):
freq_hz = 311.13
elif(piarray[i] == "2"):
freq_hz = 369.99
elif(piarray[i] == "3"):
freq_hz = 415.30
elif(piarray[i] == "4"):
freq_hz = 466.16
elif(piarray[i] == "5"):
freq_hz = 554.37
elif(piarray[i] == "6"):
freq_hz = 622.25
elif(piarray[i] == "7"):
freq_hz = 739.99
elif(piarray[i] == "8"):
freq_hz = 830.61
else:
freq_hz = 932.33
# added fall off feature
waveform = (((frames - each_sample_number) / frames)**0.5) * np.sin(
np.pi+ 2 * np.pi * each_sample_number * freq_hz / sps)*0.3
#The line above and below this one make an individual note.
waveform_integers = np.int16(waveform * 32767)
if(i == 0):
waveformc = waveform_integers
print(waveformc)
else:
waveformc = np.append(waveformc, waveform_integers, axis=None)
write('song.wav', sps, waveformc)
print("DONE")
可以在波形上看到当前设置的结果:
我在频率中添加了一个 "correction factor" 以确保每个波都以零振幅结束,并且不会有间断。它会稍微改变频率,但不会超过 1%。我就是这样做的:
cor_fac = round(each_sample_number[-1] * freq_hz / sps)/(each_sample_number[-1] * freq_hz / sps)
cor_factors.append(cor_fac)
waveform = np.sin(2 * np.pi * each_sample_number * freq_hz / sps * cor_fac)*0.3
我认为它解决了问题。
如果频率上的变化不可接受,您可以尝试更改样本阵列的开始,使其以与最后一个波形完成时相同的幅度开始。
我会尽力做到,post 在这里。
让我知道它对你有用。
编辑: 不改变声音频率的代码:
import numpy as np
from scipy.io.wavfile import write
import matplotlib.pyplot as plt
import wave
import sys
pi = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848"
piarray = list(pi)
piarray.remove(".")
print(piarray)
# Samples per second
sps = 44100
# Frequency / pitch of the sine wave
freq_hz = 440.0
# Duration
duration_s = 0.2
last_amp = 0
cor_factors = []
direction_down = False
for i in range(len(piarray)):
if(piarray[i] == "0"):
freq_hz = 277.18
elif(piarray[i] == "1"):
freq_hz = 311.13
elif(piarray[i] == "2"):
freq_hz = 369.99
elif(piarray[i] == "3"):
freq_hz = 415.30
elif(piarray[i] == "4"):
freq_hz = 466.16
elif(piarray[i] == "5"):
freq_hz = 554.37
elif(piarray[i] == "6"):
freq_hz = 622.25
elif(piarray[i] == "7"):
freq_hz = 739.99
elif(piarray[i] == "8"):
freq_hz = 830.61
else:
freq_hz = 932.33
# cor_fac = round(each_sample_number[-1] * freq_hz / sps)/(each_sample_number[-1] * freq_hz / sps)
# cor_factors.append(cor_fac)
start = np.arcsin(last_amp/0.3)
if direction_down:
start = np.pi - start
start = start/(2 * np.pi * freq_hz / sps)
each_sample_number = np.arange(start, start + duration_s * sps)
waveform = np.sin(2 * np.pi * each_sample_number * freq_hz / sps)*0.3
print(waveform[0]-last_amp)
last_amp = waveform[-1]
direction_down = waveform[-1]<waveform[-2]
#The line above and below this one make an individual note.
waveform_integers = np.int16(waveform * 32767)
if(i == 0):
waveformc = waveform_integers
print(waveformc)
else:
waveformc = np.append(waveformc, waveform_integers, axis=None)
write('song_2.wav', sps, waveformc)
print("DONE")