Problem with playing stereo waveform sounds. Can't get silent channel to be silent

332 views
Skip to first unread message

Alex Holcombe

unread,
Jun 25, 2012, 1:13:38 AM6/25/12
to psychopy-dev
Sounds can be created by passing a Nx2 array to Sound. One column of
the 2-column array is meant to be the left speaker, the other the
right speaker. When I pass all -1's to one column speaker, even though
it's supposed to be silent, you can still hear the waveform, although
at lower volume than in the speaker it was sent to.

During the second pass through the below code (testPygame=True), it
creates the same waveform, but calls pygame directly to play the
sound. In that case, it works. The left speaker is entirely silent.
Run the below code with headphones- comparing one channel to the
other- to see what I mean.

I've spent a day on this but can't work out what Psychopy is doing
differently from me calling pygame directly. At first I thought
something was wrong with the conversion from -1 to 1 to the signed 16
bits, because the pygame version seems to use the range -32767 to
32767, whereas Psychopy uses -32768 to 32767, but that doesn't seem to
be the reason for the discrepancy in silence of the left speaker.

import sys, os
from psychopy import sound,core,visual,data,event, logging
import time
import math, copy
import numpy, numpy as np
import pylab


import pygame

duration = .8 # in seconds
sample_rate = 22500 #I think only 22500 will be used by pygame when
going through psychopy. if you ask for 44100, it is ignored and 22500
still used
freq = 800
bits = -16

#below code first plays pygame version, then psychopy waveform version
#during the psychopy version, one can hear a hush of something in the
left ear. Whereas in the pygame version, nothing comes on in the left
speaker, as desired

for testPygame in [False,True]:
try:
n_samples = int(round(duration*sample_rate))
#testPygame = True
if testPygame:
max_sample = 2**(abs(bits) - 1) - 1
buf = numpy.zeros((n_samples, 2), dtype = numpy.int16)
else:
buf = numpy.zeros((n_samples, 2))
max_sample = 1.0

for s in range(n_samples):
t = float(s)/sample_rate # time in seconds
val = math.sin(2*math.pi*freq*t)#spans from -1 to 1
val = max_sample * val
if testPygame:
val = int(round(val)) #takes as 16-bit signed integer
buf[s][0] = -1 # left
buf[s][1] = val #right
if testPygame:
pygame.mixer.init(frequency = sample_rate, size = bits,
channels = 2)
print 'buf.dtype=',buf.dtype,' buf.min(),
max()=',buf.min(), ' ',buf.max()
soundMine = pygame.sndarray.make_sound(buf)
soundMine.play()
pygame.time.wait(int(round(1000*duration)))
else:
arraySnd=sound.Sound(value=buf, sampleRate=sample_rate,
bits=bits, name='', autoLog=False)
arraySnd.play()
core.wait(duration)
inits = pygame.mixer.get_init()
sampleRate, format, channels = inits
print 'sampleRate=',sampleRate, ' format=', format, '
channels=',channels
finally:
pygame.mixer.quit()
core.wait(2)

Alex Holcombe

unread,
Jul 4, 2012, 8:58:21 PM7/4/12
to psychopy-dev
This issue also came up on the psychopy-users channel, where Martin
worked out that in the psychopy case, the silent channel should be
given all zeros, not ones.
https://groups.google.com/group/psychopy-users/browse_thread/thread/40ec79fcb879e357/e94fd3d495ae3033#e94fd3d495ae3033

Doing that in combination with using expensive headphones (that
eliminate electrical cross-talk) makes the channel silent.

Alex
Reply all
Reply to author
Forward
0 new messages