如何实时改变音量
Posted
技术标签:
【中文标题】如何实时改变音量【英文标题】:How to change sound volume in real time 【发布时间】:2017-07-20 15:49:31 【问题描述】:我需要使用 Python 3.6 实时更改音量,使用 PyBinSim 和 Anaconda,但不是强制性的(可以只是 Python 3.6 和任何其他对此有用的库)。 情况如下: 使用笔记本电脑和麦克风,我们正在录制声音并立即播放它们,但我们需要在录制和播放之间更改音量。我尝试了一些代码示例,但我无法让它在没有错误的情况下工作。 有什么想法或建议吗? 提前致谢!
代码示例
import sounddevice as sd
import time
import numpy as np
from scipy import signal
duration = 10 #seconds
def callback(indata, outdata, frames, time):
outdata[:] = indata
def print_sound(indata, outdata, frames, time, status):
volum_norm = np.linalg.norm(indata) * 10
print("|") * int(volum_norm)
with sd.Stream(callback=print_sound):
sd.sleep(duration * 1000)
import sounddevice as sd
import time
import numpy as np
from scipy import signal
from ctypes import cast, POINTER
from comtypes import CLSCTX_ALL
from pycaw.pycaw import AudioUtilities, IAudioEndpointVolume
duration = 1000 #seconds
def callback(indata, outdata, frames, time, status):
if status:
print(status)
outdata[:]=indata
devices = AudioUtilities.GetSpeakers()
interface = devices.Activate(
IAudioEndpointVolume._iid_, CLSCTX_ALL, None)
volume = cast(interface, POINTER(IAudioEndpointVolume))
# Control volume
#volume.SetMasterVolumeLevel(-0.0, None) #max
#volume.SetMasterVolumeLevel(-5.0, None) #72%
volume.SetMasterVolumeLevel(-10.0, None) #72%
volume.SetMasterVolumeLevel(-10.0, None) #51%
with sd.Stream(channels=2, callback=callback):
sd.sleep(duration*1000)
第二个例子没有返回错误,但在 Win10 笔记本电脑上测试时也没有声音。
【问题讨论】:
"我尝试了一些代码示例,但无法使其正常工作"。它们是哪些代码示例,它们是什么错误?这些信息将是一个很好的起点——如果我们不知道您已经尝试过什么,那么您可能会得到很多答案,暗示您已经尝试过的事情。对任何人来说,这都不是对时间的有效利用。 很抱歉,如果我的问题没有得到正确解释。这是我第一次在这里发帖。谢谢@Kevin @Kohane 您应该编辑您的问题以包含示例代码(使用正确的代码格式)。 @Matthias 我刚刚按照您的要求添加了代码。谢谢。 我不明白第二个例子,但在第一个例子中,您可以简单地乘以indata
,然后将结果分配给outdata
。例如,您可以写outdata[:] = 0.5 * indata
将音量降低约 6 分贝。
【参考方案1】:
pyaudio 有一个阻塞回调的方法。这意味着您可以从麦克风中分块录制,然后回放。此方法适用于根据自己的需要处理音频块。
但是,audioop 提供了更简单的方法来获取每个块的功能,然后根据个人的需要增加/减少,而不是将块转换为 numpy 数组,操作并转换回块,这可能非常混乱。
以下代码是对pyaudio callback code 的修改。
根据audioop 文档(如下),我们可以使用audioop.rms
来获取片段的RMS 值(在我们的例子中是CHUNK)。虽然这对于更改音频音量不是必需的,但它可以用作调试以查看是否确实在给定的音频块上发生了更改。
audioop.rms(fragment, width):
''' Return the root-mean-square of the fragment, i.e. sqrt(sum(S_i^2)/n).
This is a measure of the power in an audio signal.'''
接下来,我们将块中的所有值乘以某个因子。 例如乘以系数 (2) 将使 RMS 值大致翻倍。并因此相应地提高音量。
audioop.mul(fragment, width, factor):
'''Return a fragment that has all samples in the original fragment
multiplied by the floating-point value factor.
Samples are truncated in case of overflow.'''
借助这两种方法,我们只需使用来自pyaudio
站点的代码,并根据倍增因子修改每个块的体积。
我还添加了代码以在列表rmsdict
的字典中为每个块收集新旧 RMS 值。由于处理中断,简单地将它们打印在屏幕上会导致咔嗒声。
麦克风的音频已录制 (3) 秒。你可以尝试不同的长度。
工作代码
import pyaudio
import audioop
from collections import OrderedDict
class DefaultListOrderedDict(OrderedDict):
'''
Ordered Dict of list to hold old and new RMS values
'''
def __missing__(self,k):
self[k] = []
return self[k]
FORMAT = pyaudio.paInt16
CHUNK = 2048
WIDTH = 2
CHANNELS = 1
RATE = 44100
RECORD_SECONDS = 3
FACTOR = 2
rmsdict = DefaultListOrderedDict()
p = pyaudio.PyAudio()
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
output=True,
frames_per_buffer=CHUNK)
print("* recording from microphone")
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
rmsdict["chunk".format(i)].append(audioop.rms(data, 2))
new_data = audioop.mul(data, WIDTH, FACTOR)
rmsdict["chunk".format(i)].append(audioop.rms(new_data, 2))
stream.write(new_data, CHUNK)
print("* done recording")
stream.stop_stream()
stream.close()
p.terminate()
以下是来自rmsdict
的数据。为了能见度,我已经截断了它。
Win32 上的 Python 2.7.9(默认,2014 年 12 月 10 日,12:24:55)[MSC v.1500 32 位(英特尔)] 输入“copyright”、“credits”或“license()”了解更多信息。
================================= 重启============== ===================
从麦克风录音 完成录音rmsdict DefaultListOrderedDict([('chunk0', [71, 143]), ('chunk1', [77, 155]), ('chunk2', [45, 91]), ('chunk3', [29, 59]), ('chunk4', [33, 66]), ('chunk5', [35, 71]), ('chunk6', [27, 54]), ('chunk7', [17, 34]), ('chunk8', [18, 36]), ('chunk9', [142, 285]), ('chunk10', [1628, 3257]), ('chunk11', [2666, 5333]), ('块 12', [2174, 4348]), .. .. ('chunk51', [1723, 3446]), ('chunk52', [1524, 3049]), ('chunk53', [1329, 2659]), ('chunk54', [1166, 2333]), ('chunk55', [573, 1147]), ('chunk56', [1777, 3555]), ('chunk57', [1588, 3176]), ('chunk58', [698, 1397]), ('chunk59', [383, 767]), ('chunk60', [152, 305]), ('chunk61', [799, 1599]), ('chunk62', [2158, 4316])])
【讨论】:
以上是关于如何实时改变音量的主要内容,如果未能解决你的问题,请参考以下文章