Audio output from BCPy2000

Forum for discussion on different user applications
Locked
boulay
Posts: 382
Joined: 25 Dec 2011, 21:14

Audio output from BCPy2000

Post by boulay » 24 Jan 2012, 20:57

Eventually I will use a USB device to send a TTL but for now I would like to use audio output as a placeholder.

I have a class (GenericStimulator , which I subclass later) which has the following code:

Code: Select all

from SigTools import Stimuli
from WavTools import PyAudioInterface
class GenericStimulator(object):
    def __init__(self):
        zap_wav = Stimuli.zap(msec=10, shape='square')
        self.player = PyAudioInterface.player(w=zap_wav, verbose=True, buffersize=300, dev=None)
    def trigger(self):
        self.player.play()
        print "triggered"
The stimulator is initialized during the Application's Initialize hook. After pressing "Set Config" I can use the python console to enter
self.stimulator.trigger()
and I hear a small pop and see the printed output. However, after I press start, this command no longer generates an audio output though it still prints to the console. I'm not planning on using the audio output in the end but I may use it for a different purpose in the future. Also, I am a bit worried that whatever is blocking the audio output might also block the DAO once I get that working.

What am I doing wrong? Is audio output special in that it requires its own thread?

jhill
Posts: 31
Joined: 17 Nov 2009, 15:15

Re: Audio output from BCPy2000

Post by jhill » 24 Jan 2012, 22:13

Are you on Vista and/or Windows 7? Check the system volume mixer before, during and after the run. Is the "VisionEgg" (or possibly "PythonApp") entry of the windows mixer muted during the run? If you unmute it by hand, is all suddenly well again?

If so, what's happening is this. During Initialize, the BCPy2000 framework calls the init_volume() method, which attempts to import WavTools.MasterVolume from the BCPy2000 tools (since the latter are intended to be optional, it simply prints a warning if it fails, and everything carries on). If successful, it uses the MasterVolume module to read the system volume setting and store it; it also installs two callbacks: deferred instructions to call the volume() method to change the master volume on every StartRun and StopRun. The underlying logic is (or at least, was, in the WinXP days) that you want the system to set itself to the same master volume for every run, to ensure consistent stimulus properties that are not at the mercy of the user/experimenter fiddling with the system volume. You also want to set it back the way it was at the end of each run---to reduce the temptation for such fiddling, and/or possibly to avoid deafening consequences next time there's a system alert sound.

The problem is probably that the MasterVolume module contains a hideous hardcoded kludge for addressing the correct windows mixer control. It seemed to work OK on many WinXP distros but has failed on the one or two Vista/7 machines I have ever had my hands on, misaddressing the mixer and turning the "mute" checkbox on and off instead of turning the volume slider up and down (the tragic difference between a mute control and a volume slider is that 0 is loud and 1 is silent for the former, whereas vice is versa for the latter). If this is your syndrome, you're the first to send me a report confirming it from outside.

And if so, your alternatives are as follows.

Solution (1) is to switch from a fixed release of the BCPy2000 python files to the svn version, in which MasterVolume contains a kludged fix on top of the existing kludge. It has the additional advantage that you can update your BCPy2000 framework whenever there are new bugfixes and added features (it's fairly stable, however). Here's how you do it: go into your python distro's site-packages directory ( maybe it's at C:\FullMonty254_20110710\App\Lib\site-packages ). Either remove the BCPy2000-blah folder that's there entirely or (more reversibly) just remove the bcpy2000-blah entry from the easy_install.pth text file that's sitting there. That's the old version out of the way. Now, substitute an svn-controlled copy of BCPy2000. There are two ways of doing this: (1A) check out just the minimal amount right here, and keep it version-controlled right here (checkout will take only a few seconds); (1B) link to your big global svn working-copy of BCI2000 that you keep elsewhere on the hard disk (a full BCI2000 working copy is a huge thing taking a long while to download, but if you already have one anyway, you'll only have to worry about version-controlling things in one tree---this is how I do it in the lab). To do (1A) and check out the minimal amount, you want to right-click on some whitespace in the site-packages folder and ask TortoiseSVN to check out http://www.bci2000.org/svn/trunk/src/co ... k/BCPy2000 . If you've done it right, site-packages/BCPy2000/__init__.py should exist. To go (1B) and walk the path of the One True Working Copy, create a text file of your own inside site-packages, called something like bcpy2000.pth . This file should have one line of content specifying either a relative or an absolute path to a directory such as the following (and yes, it's better if the slashes go forward, even on windows):

Code: Select all

../../../../MyBCI2000WorkingCopy/src/contrib/BCPy2000/framework
The great-great-grandparent of this target directory, which I've called MyBCI2000WorkingCopy in this example, is the "trunk" directory of your BCI2000 source-included distro.

If this has worked, you should be able to restart BCPy2000 (or any IPython session in which you import BCPy2000.Paths), type

Code: Select all

edit WavTools.MasterVolume
and see that the updated version of this file contains comments marked ***

Code: Select all

#*** extreme empirical adhockery ahead: if anyone knows how to navigate the rocks of the windows API to do this properly, please tell me!
Following that there are a few lines that, in contrast to the older version you may have, have successfully worked around the Vista/7 muting problem on the few machines I have encountered.


Solution (2) is not really a solution at all but rather a hack on top of a hack. Simply disable the volume() method by overshadowing it in your BciApplication class as follows:

Code: Select all

def volume(self, val): pass
Now you'll have no automatic volume control at all: make sure you check the system volume by hand on every run. Also, although (2) is simple, I'm recommending solution (1) in your particular case because I'm sure there are other issues we'll be working through together in future (and I wanted to get the svn-howto written down somewhere).

boulay
Posts: 382
Joined: 25 Dec 2011, 21:14

Re: Audio output from BCPy2000

Post by boulay » 24 Jan 2012, 22:52

That was indeed the problem and your solution solved it.
Thank you.

Locked

Who is online

Users browsing this forum: No registered users and 1 guest