Pyaudio 如何只在一个扬声器上播放声音

Pyaudio How to get sound on only one speaker

我在一个学校项目中使用 pyaudio,我试图让声音一次只在一个扬声器上播放。我的代码是这样的:

import pyaudio

p = pyaudio.PyAduio()

def play_wave(stream, wave):
    chunks = []
    chunks.append(wave)
    chunk = concatenate(chunks)*0.1
    stream.write(chunk.astype(np.float32).tostring())

def play_sound(freq, t, A=0.2):
    wave, A = wavefunc(t, freq, A=A)
    S = sigmoid(t)
    wave = wave*S
    stream = p.open(channels=1, rate=44100, format=pyaudio.paFloat32, output=True)
    play_wave(stream,wave)
    stream.close()

wavefunc 只是生成一个波。

有人知道怎么办吗?

现在您正在使用 channels=1,即单声道音频流。您需要使用两个通道进行立体声,并分别为左右通道生成数据。

Here's a short tutorial 关于如何创建立体数据。

我自己也找到了一个方法。我只将 play_sound 函数更改为

def play_sound(freq, t, A=0.2):
    wave, A = wavefunc(t, freq, A=A)
    S = sigmoid(t)
    signal = wave*S
    stereo_signal = zeros([len(signal), 2])   #these two lines are new
    stereo_signal[:, 1] = signal[:]     #1 for right speaker, 0 for  left
    stream = p.open(channels=2, 
                rate=44100, 
                format=pyaudio.paFloat32, 
                output=True)
    play_wave(stream,stereo_signal)
    stream.close()

您可以使用 http://python-sounddevice.rtfd.org/.

而不是 PyAudio

play() 函数接受 select 要播放的频道的 mapping 参数。

您可以尝试在右声道播放单声道 NumPy 数组:

import sounddevice as sd
sd.play(signal, samplerate=44100, mapping=[2])

这是另一个简单易用的立体声播放库的示例代码。

import numpy as np
import simpleaudio as sa
import matplotlib.pyplot as plt
# calculate note frequencies Hertz
A_freq = 120
Csh_freq = A_freq * 2 ** (4 / 12)

E_freq = A_freq * 2 ** (7 / 12)
print(Csh_freq)
print(E_freq)
# get timesteps for each sample, T is note duration in seconds
sample_rate = 44100
T = 0.25
t = np.linspace(0, T, T * sample_rate, False)
#print(t)
# generate sine wave notes
A_note = np.sin(A_freq * t * 2 * np.pi)
Csh_note = np.sin(Csh_freq * t * 2 * np.pi)
E_note = np.sin(E_freq * t * 2 * np.pi)

plt.subplot(211)
plt.plot(A_note)
# concatenate notes
audio = np.hstack((A_note, Csh_note,E_note))
#print(audio)
# normalize to 16-bit range
audio *= 32767 / 1 * np.max(np.abs(audio))
plt.subplot(212)
#print(audio)
# convert to 16-bit data
audio = audio.astype(np.int16)

# create stereo signal with zeros
stereo_signal = np.zeros([int(sample_rate*T*3),2],dtype=np.int16)   
stereo_signal[:,1] = audio[:]
print(stereo_signal)

#print(audio2)
plt.plot(audio)
# start playback
play_obj = sa.play_buffer(stereo_signal, 2, 2, sample_rate)

#plt.show()
# wait for playback to finish before exiting
play_obj.wait_done()