Using sound.apodize function on type soundPyo

Hi everyone,

I’m trying to write a program which changes frequencies when the user scrolls up or down. I’ve got it working well, but I would like to create hamming windows in order to remove the clicking sound when the sine waves stop and play.

The apodize function looks like it should work great, but every time I try to use it and pass it my sound and the sampling rate, it sends an error message as follows:
TypeError: object of type ‘SoundPyo’ has no len()

I also tried passing sound to the function in the form of Pygame and a .wav file with the same result.

Any ideas? I’m baffled.

I doubt anyone’s going to have much to say if you don’t include some more info. A minimal working example, a full error traceback, this will help encourage responses.

1 Like

apodize() expects a numpy array as the first argument. The error message is because you are passing a SoundPyo object, rather than the values.

If you are creating a new Sound object for each different frequency, just use hamming=True and it will automatically apply a 5ms hamming window for you.

Thanks for the advice! I’m pretty new to coding in general. I’ll post my code below so you guys can see what I’m trying to do.

Hey Jeremy,
Thanks for the response! So when I added the hamming=True to my sound objects, the updated sound played some really funky stuff. I think the sound updates too much for the hamming window to work well…

Sorry that my code looks terrible, I tried to clean it up but I’ve mostly gotten to this point by stealing similar code and changing it :stuck_out_tongue: So I’m basically trying to get it to do what it does, but with less of the annoying clicking sounds when the mouse wheel is moved. Here’s the current (simplified) version of my code:

from psychopy import locale_setup, gui, visual, core, data, event, logging, sound
from psychopy.constants import (NOT_STARTED, STARTED, PLAYING, PAUSED,
STOPPED, FINISHED, PRESSED, RELEASED, FOREVER)
import numpy as np # whole numpy lib is available, prepend 'np.'
from numpy.random import random, randint, normal, shuffle
import time
import random

myWin = visual.Window((800.0,800.0),allowGUI=False,winType='pyglet',
monitor='testMonitor', units ='deg', screen=0)

def updateTheSound(freq): #to constantly update the sound when the mouse wheel is moved
    sound_1 = sound.Sound(freq, secs=-1)
    sound_1.setVolume(1)
    return sound_1

freq = 440
freq2 = freq
sound_1 = sound.Sound(freq, secs=-1)
sound_1.setVolume(1)

trialClock = core.Clock()
trialClock.reset() # clock
t = trialClock.getTime()

myMouse = event.Mouse(win=myWin) #wheel_dY is the one that changes

myWin.flip()
sound_1.play()
while True: #keep going forever
    wheel_dX, wheel_dY = myMouse.getWheelRel()
    if (freq2 !=freq and wheel_dY==0):
        sound_1.stop()
        sound_1.play()
    freq = freq2
    freqchange = freq * .05946 / 20 #change the amount that the frequency changes with the mouse wheel
    if wheel_dY != 0:
        sound_1.stop()
        freq2 = freq + (wheel_dY * freqchange)
        sound_1 = updateTheSound(freq2)
    for key in event.getKeys():
        if key in ['escape']:
            sound_1.stop()
            myWin.close()
            core.quit()

please edit your post and surround your code in triple back-ticks ``` so that it maintains indentation correctly

1 Like

Hi Tony,

your problems with clicks seem to be caused by the sound_1.stop() commands before the sound had ended. Yet another source is distortion due to not limiting the accumulative volumes of two simultaneously playing sounds to 1 (or 100%)
Here is a little piece of code demonstrating both issues:

from psychopy import core, prefs, sound
prefs.general['audioLib'] = ['pyo']
prefs.general['driver'] = ['portaudio']
s2 = sound.Sound(value = 220, secs = 2.5)
#s2.setVolume(0.5)
s2.play()
core.wait(0.5)
for freq in ['A', 'A', 'A']:
    s1 = sound.Sound(value = freq, secs = .5)
    #s1.setVolume(0.5)
    s1.play()
    core.wait(0.5)
    s1.stop()
core.wait(0.5)
s2.stop()
s1.stop()
core.quit()

If you un-comment the two lines containing setVolume(...) the distortion is gone. Then, comment out the s1.stop() line in the for loop and the click after each ‘A’ disappears.
Cheers,
Michael

Hey Michael,

I tried out your code and it doesn’t seem to be working on my computer on psychopy… There’s bad distortion in the first version (withough the setVolume), but when I un-comment those, it still distorts heavily, the sounds are just quieter.

It also didn’t get any better when I took out the s1.stop line in the for loop.

I’ve tried a few more things, and was hoping to try to use a short fade-out/fade-in function between every time the sound is restarted. The problem I ran into there was that pyo sound doesn’t contain a fade-in function, and when I tried to use pygame nothing seemed to work at all. Any ideas how I could get this to work? I’ll keep trying different things on my code, I get the feeling I’m fairly close to an answer.

Thanks everyone for the ideas!
Tony

Hi Tony,

try using lower levels in setVolume(). Maybe something odd is happening your Line out. I tried the two sound chips built into my pc and the level of one of them is far higher than the other. Maybe the distortion is simply an effect of overdrive?

Michael

1 Like

With the new sounddevice backend (replacement of pygame and pyo for sounds) the option to add hamming will exist for all sounds (files, frequencies or notes). For now I still haven’t set it to implement the hamming window if you issue a stop() function before the sound was due to end but even that could be added if needed.

Wow, this is really very much appreciated! And it sounds (no pun intended) cool as well. For the moment we will experiment with shortening the duration of sounds. We’ll report back whether this works out.