PsychoPy ASIO Implementation

681 views
Skip to first unread message

Scott Novich

unread,
Sep 6, 2011, 4:30:45 PM9/6/11
to psychopy-dev
Not sure if anyone's solved this yet, but I noticed that there's
currently no ASIO support for PsychoPy. I found a quick fix using a
python library called pyo, available at http://code.google.com/p/pyo/

After installing pyo (the Windows installer places the lib in C:
\Python-2.6\...\site-packages - so you'll need to move it to your
PsychoPy's site-packages dir if you're using standalone), you can use
the following lines of code in your PsychoPy Project:

0. from pyo import *

1. soundfile="path-to-audio-file.wav" # Playing recorded audio
stimulus from memory is lower latency than generating on the fly

2. s = Server(sr=44100,nchnls=2, duplex=0) # nchannels = 1 is probably
OK, and so is a lower sampling rate, unless you need hifi audio

3. s.setOutputDevice(8) # call pa_list_devices() in shell to see
available cards and corresponding index numbers

4. s.setBufferSize(128) # ~13.1ms (or ~1 frame delay) for me.
Determined using a demo version of Ableton Live - IF USING ASIO4ALL,
BE SURE TO CHECK ASIO4ALL Panel for ACTUAL samples used (buggy...).

5. s.boot() #boot the sound server

6. sndstim = SfPlayer(soundfile,speed=1,loop=False)
# create the sound stimulation object used by the pyo library, to
generate, call: sndstim.out()

7. s.start() # enable audio playback

8. Rest of your code.... - be sure to account for the latency if it's
larger than a frame-length in delay

9. s.stop() # disable audio playback

10. s.shutdown() # stop server <-IMPORTANT! Otherwise Python will
crash


Optional Additions:
- ASIO4ALL (if you only have a stock soundcard available to you that
doesn't come w/ ASIO drivers) - http://www.asio4all.com/
- Ableton Live (Demo) http://www.ableton.com/downloads - doesn't
expire (you just can't save). The sound card preferences menu will
show you the expected in/out latencies based on the buffer size (and
also has a nice little tone generator for testing w/ your settings),
so you can account for this in your code.

ASIO4ALL is a bit buggy when it comes to setting the buffer...
To set buffer: 1) Start (run) Project (dont engange in it)
2) use ASIO4ALL panel to adjust to a buffer size
3) shut down project
4) restart project, changes should (roughly) take effect

Best,
Scott Novich

Gary Lupyan

unread,
Sep 6, 2011, 4:55:30 PM9/6/11
to psycho...@googlegroups.com
This is fantastic! Thank you so much!!! I've been waiting for this....

-----------------------------------------------------
Gary Lupyan - lup...@wisc.edu
Assistant Professor of Psychology
University of Wisconsin, Madison
http://sapir.psych.wisc.edu
-----------------------------------------------------

boomtechnology

unread,
Sep 6, 2011, 5:15:54 PM9/6/11
to psycho...@googlegroups.com
My pleasure!

An additional quick note: As I mentioned, I strongly suggest using an audio-file from memory over generating sound on the fly (if you need the low-latency). I would just make sure the audio file sample-rate (SR) matches the SR of the pyo server. I haven't tested it yet, but using lower sample rate audio will probably allow you to push your buffer-size even lower without artifacts. Here's a little script I use for generating tones in matlab http://pastebin.mozilla.org/1324126

Best,
Scott Novich

Jonathan Peirce

unread,
Sep 6, 2011, 5:37:42 PM9/6/11
to psycho...@googlegroups.com
Indeed, that's great! Thanks for the pointer Scott!

I guess the next step will be to create a Sound class based on pyo, that
can eventually replace the pygame sounds. Would definitely also need a
way to control buffer size (and it will be interesting the trade-off
works with low-latency versus dropped frames). I wonder whether the use
of the 'server' arrangement is a way to get around the python GIL, so
that all the sound handling can run on a separate CPU core(?).

For on-the-fly sounds, PsychoPy currently premakes a numpy array and
passes that to the handling lib - it doesn't create each buffer as
needed. Can pyo receive an array instead of a file? That shouldn't have
any overhead once loaded.

The creation/destruction of the sound 'server' could probably be handled
automatically using a __del__ method for the sounds. Would need to test
how many sound servers are allowed simultaneously.

will be great to see how this develops!
Jon

--
Dr. Jonathan Peirce
Nottingham Visual Neuroscience

http://www.peirce.org.uk/

Gary Lupyan

unread,
Sep 6, 2011, 9:50:48 PM9/6/11
to psycho...@googlegroups.com
Hi Scott, I was able to get it working with ASIO4ALL within minutes.
This is terrific.

I noticed that when trying to play a mono file it only plays it in one
channel. If I convert it to stereo (by just duplicating the info in
both channels) it works fine. The default behavior in windows at
least is to send the sound from mono files to both channels. Is there
a way to get pyo to do that?

Thanks!

-----------------------------------------------------
Gary Lupyan - lup...@wisc.edu
Assistant Professor of Psychology
University of Wisconsin, Madison
http://sapir.psych.wisc.edu
-----------------------------------------------------


On Tue, Sep 6, 2011 at 3:30 PM, Scott Novich <boomtec...@gmail.com> wrote:

> s.setOutputDevice(8)

boomtechnology

unread,
Sep 6, 2011, 11:54:19 PM9/6/11
to psycho...@googlegroups.com
Hey Jon - I'm fairly certain pyo can receive an array using something like the TableRead() function (see the table stuff in http://www.iact.umontreal.ca/pyo/manual/)... I should also mention there is another sound library I was playing with before pyo, with some success (though I couldn't get ASIO working). SndObj - http://sndobj.sourceforge.net/ , if any of the devs want to browse through that as well.

Best!
Scott

boomtechnology

unread,
Sep 6, 2011, 11:58:30 PM9/6/11
to psycho...@googlegroups.com
Hi Gary,

Did you try setting nchnls=1 when you initialized the server? I'm not sure off-hand about the nuances of how windows drivers vs. ASIO interprets mono, but I'll also play around with this a little bit more tomorrow when I get back to the lab.

Best!
Scott
Reply all
Reply to author
Forward
0 new messages