hey mario-
playing with some streaming audio ideas. 2 issues -- if i specify a
device in psychportaudio('open'), then subsequent calls to
psychportaudio('getstatus') cause a silent crash. my function exits,
an indefinitely repeating sound will keep playing, etc. no error
output at all. this happens whether or not i've started output. if i
don't specify a device in the call to 'open,' 'getstatus' works fine.
second, i'm trying to use streaming with either directsound or mme --
no asio in this case cuz i don't care about latency. i do care about
sound continuity; i'm doing realtime synthesis. i'm not getting
underflows reported from 'fillbuffer,' but i get terrible sound
discontinuities throughout the sound with directsound. with mme,
everything's great. in the following demo code, i use the mouse x,y
to set frequency and amplitude. i precompute a full amplitude buffer
for each possible frequency, and then scan it for its first and last
upward going zero crossing, so that buffer transitions will be smooth.
this means that each of my calls to fillbuffer has a slightly
different length.
you recommend directsound over mme -- i expected that neither should
have problems with streaming, just absolute latency. any idea why
directsound has discontinuities?
'getstatus,' when it works, indicates i'm not taxing the cpu (CPULoad
= ~.005). the task manager shows i'm pegging one of my cores -- does
that mean that streaming 'fillbuffer' does not sleep the thread while
its waiting for room?
-erik
function streamTest
clc
clear all
ListenChar(2)
priority(maxpriority('kbcheck','getmouse'));
initializepsychsound
d=[];
hostapi='MME' ; %'Windows DirectSound' %vs. 'MME'
hostname='SoundMAX HD Audio O'; %'Primary Sound Driver' (wds only)
vs. 'SoundMAX HD Audio O' vs. 'Microsoft Sound Mapper - Output' (mme only)
devices = PsychPortAudio('GetDevices');
for i=1:length(devices)
if devices(i).NrOutputChannels>0 &&
strcmp(devices(i).HostAudioAPIName,hostapi) &&
strcmp(devices(i).DeviceName,hostname)
d=devices(i).DeviceIndex;
break
end
end
if isempty(d)
warning('host not found, using default')
end
pahandle = PsychPortAudio('Open',d); %if d==[], GetStatus works,
otherwise it silently crashes the program
numoctaves=8;
fundamental=27.5;
steps=12;
freqs=logspace(log10(fundamental),log10(fundamental*2^numoctaves),numoctaves*steps+1);
buffsize=2/fundamental;
amp=1;
%status = PsychPortAudio('GetStatus', pahandle) %GetStatus fails when
device specified
status.SampleRate=44100; %hardcoded cuz GetStatus fails when device
specified
for i=1:length(freqs)
f{i}=repmat(makebeep(freqs(i),buffsize,status.SampleRate),2,1);
zeroCrossings=find(diff(f{i}(1,:)>0)==1);
upwardZeroCrossings=[min(zeroCrossings) max(zeroCrossings)-1];
f{i}=f{i}(:,upwardZeroCrossings(1):upwardZeroCrossings(2));
f{i}=f{i}-repmat(mean(f{i}')',1,size(f{i},2));
f{i}=amp*f{i}/max(abs(f{i}(:)));
end
s=Screen('Resolution', 0);
numBuffs=2;
[x y]=getmouse;
ind=1+floor((length(freqs)-1)*x/s.width);
under=PsychPortAudio('FillBuffer', pahandle, repmat(f{ind},1,numBuffs),0);
done=false;
'hit s for status (crashes if audio device specified), space to quit'
PsychPortAudio('Start', pahandle, 0);
while ~done
[keyIsDown, secs, keyCode] = KbCheck;
if keyIsDown
if keyCode(kbname('space'))
done=true;
end
if keyCode(kbname('s'))
status = PsychPortAudio('GetStatus', pahandle) %GetStatus
fails when device specified
'hit s for status (crashes if audio device specified),
space to quit'
end
end
[x y]=getmouse;
if any([x y])<0 || any([x y]>[s.width s.height])
'mouse error'
[x y]
[s.width s.height]
end
ind=1+floor((length(freqs)-1)*x/s.width);
if PsychPortAudio('FillBuffer', pahandle, f{ind}*y/s.height ,1)
'got an underflow'
end
end
PsychPortAudio('Stop', pahandle);
PsychPortAudio('Close');
ListenChar(0)
priority(0);
playing with some streaming audio ideas. 2 issues -- if i specify a
device in psychportaudio('open'), then subsequent calls to
psychportaudio('getstatus') cause a silent crash. my function exits,
an indefinitely repeating sound will keep playing, etc. no error
output at all. this happens whether or not i've started output. if i
don't specify a device in the call to 'open,' 'getstatus' works fine.
second, i'm trying to use streaming with either directsound or mme --
no asio in this case cuz i don't care about latency. i do care about
sound continuity; i'm doing realtime synthesis. i'm not getting
underflows reported from 'fillbuffer,' but i get terrible sound
discontinuities throughout the sound with directsound. with mme,
everything's great. in the following demo code, i use the mouse x,y
to set frequency and amplitude. i precompute a full amplitude buffer
for each possible frequency, and then scan it for its first and last
upward going zero crossing, so that buffer transitions will be smooth.
this means that each of my calls to fillbuffer has a slightly
different length.
you recommend directsound over mme -- i expected that neither should
have problems with streaming, just absolute latency. any idea why
directsound has discontinuities?
'getstatus,' when it works, indicates i'm not taxing the cpu (CPULoad
= ~.005). the task manager shows i'm pegging one of my cores -- does
that mean that streaming 'fillbuffer' does not sleep the thread while
its waiting for room?
-erik
function streamTest
clc
clear all
ListenChar(2)
priority(maxpriority('kbcheck','getmouse'));
initializepsychsound
d=[];
hostapi='MME' ; %'Windows DirectSound' %vs. 'MME'
hostname='SoundMAX HD Audio O'; %'Primary Sound Driver' (wds only)
vs. 'SoundMAX HD Audio O' vs. 'Microsoft Sound Mapper - Output' (mme only)
devices = PsychPortAudio('GetDevices');
for i=1:length(devices)
if devices(i).NrOutputChannels>0 &&
strcmp(devices(i).HostAudioAPIName,hostapi) &&
strcmp(devices(i).DeviceName,hostname)
d=devices(i).DeviceIndex;
break
end
end
if isempty(d)
warning('host not found, using default')
end
pahandle = PsychPortAudio('Open',d); %if d==[], GetStatus works,
otherwise it silently crashes the program
numoctaves=8;
fundamental=27.5;
steps=12;
freqs=logspace(log10(fundamental),log10(fundamental*2^numoctaves),numoctaves*steps+1);
buffsize=2/fundamental;
amp=1;
%status = PsychPortAudio('GetStatus', pahandle) %GetStatus fails when
device specified
status.SampleRate=44100; %hardcoded cuz GetStatus fails when device
specified
for i=1:length(freqs)
f{i}=repmat(makebeep(freqs(i),buffsize,status.SampleRate),2,1);
zeroCrossings=find(diff(f{i}(1,:)>0)==1);
upwardZeroCrossings=[min(zeroCrossings) max(zeroCrossings)-1];
f{i}=f{i}(:,upwardZeroCrossings(1):upwardZeroCrossings(2));
f{i}=f{i}-repmat(mean(f{i}')',1,size(f{i},2));
f{i}=amp*f{i}/max(abs(f{i}(:)));
end
s=Screen('Resolution', 0);
numBuffs=2;
[x y]=getmouse;
ind=1+floor((length(freqs)-1)*x/s.width);
under=PsychPortAudio('FillBuffer', pahandle, repmat(f{ind},1,numBuffs),0);
done=false;
'hit s for status (crashes if audio device specified), space to quit'
PsychPortAudio('Start', pahandle, 0);
while ~done
[keyIsDown, secs, keyCode] = KbCheck;
if keyIsDown
if keyCode(kbname('space'))
done=true;
end
if keyCode(kbname('s'))
status = PsychPortAudio('GetStatus', pahandle) %GetStatus
fails when device specified
'hit s for status (crashes if audio device specified),
space to quit'
end
end
[x y]=getmouse;
if any([x y])<0 || any([x y]>[s.width s.height])
'mouse error'
[x y]
[s.width s.height]
end
ind=1+floor((length(freqs)-1)*x/s.width);
if PsychPortAudio('FillBuffer', pahandle, f{ind}*y/s.height ,1)
'got an underflow'
end
end
PsychPortAudio('Stop', pahandle);
PsychPortAudio('Close');
ListenChar(0)
priority(0);