初学者 python 编程帮助交叉淡入淡出声音
Posted
技术标签:
【中文标题】初学者 python 编程帮助交叉淡入淡出声音【英文标题】:Beginner python programming help to crossfade sounds 【发布时间】:2013-11-22 01:34:53 【问题描述】:您好,我正在上编程课,但我完全被一个问题迷住了。我们需要把两个声音加在一起。但是第一个声音以最大音量开始,第二个声音开始静音,然后放慢平衡,直到第一个声音静音,第二个声音达到最大音量。所以我能够把声音放在一起,但我不知道如何让它们在声音的过程中变得更响亮。
def mergeSounds(s1, s2):
sr = int(getSamplingRate(s1))
newSound = makeEmptySound(getLength(s1), sr)
for t in range(getLength(newSound)):
sv1 = getSampleValueAt(s1, t)
sv2 = getSampleValueAt(s2, t)
setSampleValueAt(newSound, t, sv1 + sv2)
return newSound
【问题讨论】:
这个问题似乎离题了,因为它与 Python 甚至编程本身无关。 @martineau,我不同意。知道如何在一个范围内线性增加一个值是一项非常常见的编程任务。 【参考方案1】:这本身不是 python 问题,而是解构任务问题。
音量
首先,您需要知道如何调整声音的音量。这其实超级简单!
PCM 声音(您正在使用的声音)存储为距离零的有符号距离。我喜欢将其可视化为“扬声器锥体所在的位置”——零表示扬声器处于静止状态,负值将扬声器锥体吸入,正值将扬声器推出。
如果您曾经看过扬声器,就会知道扬声器移动得越远,声音就越大。为了使扬声器移动得更少,请将每个样本乘以 0 到 1 之间的某个数字。
所以,要缩放你的两个声音,这样的方法是可行的:
def amplify(s1, amplify_value):
sr = int(getSamplingRate(s1))
newSound = makeEmptySound(getLength(s1), sr)
for t in range(getLength(newSound)):
sv1 = getSampleValueAt(s1, t)
setSampleValueAt(newSound, t, sv1 * amplify_value)
return newSound
爬坡量
现在您知道如何让声音变大或变小,您需要知道随着时间的推移每个声音的幅度会发生什么变化。
开始时第一个声音的幅度应该是多少?第二个呢?
在开始时,第二个声音应该是无声的,所以它的幅度为零。第一个声音应该是全音量,所以它的幅度是1:
firstSoundVolume = 1
secondSoundVolume = 0
最后是相反的:
firstSoundVolume = 0
secondSoundVolume = 1
你怎么能用这个?基本上,您希望将每个幅度从其起始值平滑地滑动到其结束值。有很多不同的方法可以做到这一点,但我最喜欢的是这样的:
-
以秒或样本为单位计算出您在淡入淡出的位置。你打电话给这个
t
,这是完美的。
将其转换为交叉渐变中的位置,作为交叉渐变长度的一部分。 (即t
/length
)。我会打电话给u
。
您现在可以直接使用u
进行缩放(就像 gnibbler 的示例一样),或者通过另一个函数来获取缩放因子。
这里又是 gnibbler 的示例,扩展为明确包含 u
:
n = getLength(newSound)
for t in range(n):
u = t / float(n)
sv1 = getSampleValueAt(s1, t)
sv2 = getSampleValueAt(s2, t)
setSampleValueAt(newSound, t, sv1 * (1-u) + sv2 * u)
其他交叉淡入淡出功能
现在你有了 0 u
这是用函数完成的相同的线性淡入淡出。
def linear(u):
return (1-u, u)
def mergeSounds(s1, s2, fade=linear):
"""Crossfade two sounds, using linear fading by default"""
sr = int(getSamplingRate(s1))
newSound = makeEmptySound(getLength(s1), sr)
n = getLength(newSound)
for t in range(n):
u = t / float(n)
amp1, amp2 = fade(u)
sv1 = getSampleValueAt(s1, t)
sv2 = getSampleValueAt(s2, t)
setSampleValueAt(newSound, t, (sv1 * amp1) + (sv2 * amp2))
return newSound
现在你可以做一些其他的交叉淡入淡出,比如这些:
def quadratic_out(u):
u = u * u
return (1-u, u)
def quadratic_in(u):
u = 1-u
u = u * u
return (u, 1-u)
def linear_bounce(u):
u = 2 * ( 0.5-u if u > 0.5 else u)
return (1-u, u)
【讨论】:
【参考方案2】:n = getLength(newSound) - 1.0 # n should be a float for Python2
for t in range(int(n + 1)):
sv1 = getSampleValueAt(s1, t)
sv2 = getSampleValueAt(s2, t)
setSampleValueAt(newSound, t, sv1 * (1 - t / n) + sv2 * t / n)
【讨论】:
谢谢。非常感谢 其实应该是sv1*(1-t/float(n-1)) + sv2*t/float(n-1)
,否则最终的值不会是sv2
。
@martineau,是的。我用稍微不同的方式修复了它
@martineau 现在你需要特殊情况的长度为一的声音
@kibibu:在我的评论提到的代码版本和当前版本中都是如此,并且很容易添加检查。 IMO,这个要求是可以接受的,因为一步不可能也不可能在两个不同的值之间变化。实际上,无论哪种方式,只允许引发异常都可以,因为尝试它没有意义。以上是关于初学者 python 编程帮助交叉淡入淡出声音的主要内容,如果未能解决你的问题,请参考以下文章