我需要使用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笔记本电脑上测试时,也没有声音可以听到。
答案 0 :(得分:1)
pyaudio有一种阻止回调的方法。这意味着您可以从麦克风中分块录制,然后播放它们。此方法适用于根据个人需要处理音频块。
然而,audioop不是将块转换为numpy数组,而是操纵和转换回块,这可能相当混乱,pyaudio callback code提供了更简单的方法来获取每个块的功率,然后根据需要增加/减少。 / p>
以下代码是对audioop的修改。
根据{{3}}文档(下面),我们可以使用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
的dict中收集旧的和新的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()”以获取更多信息。
================================ RESTART ============== ==================
- 从麦克风录制
- 完成录制
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]),(' chunk12',[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])])