Audio I/O Demo 3 – Streaming continuous audio

In this demo, we take a sound file and stream it continuously to the device.

Note

You can only play audio on the full version of a device; the lite version does not have audio playback capabilities.

In this demo, to write the Audio Buffer, we call Datapixx('WriteAudioBuffer', waveData(:,1:nBufferFrames), 0);, which fits as much data as the buffer can take, at address zero.

We create the Audio Schedule for playback, and we write the new frames that were not written yet: Datapixx('WriteAudioBuffer', waveData(:, nextWriteFrame: nextWriteFrame+nStreamFrames-1), -1); the -1 here signifies that we are continuously streaming audio and to continue without changing the address.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
function DatapixxAudioStreamDemo(wavFilename)
% DatapixxAudioStreamDemo([wavFilename=funk.wav])
%
% Demonstrates how to continuously stream an audio waveform to the DATAPixx CODEC.
%
% Optional argument:
%
% wavFilename = Name of a .wav sound file to load and play.
%               Otherwise the funk.wav provided with PsychToolbox is used.
%
% Also see: DatapixxAudioDemo
%
% History:
%
% Oct 1, 2009  paa     Written
% Oct 29, 2014 dml     Revised 

AssertOpenGL;   % We use PTB-3

% Get the .wav filename
if nargin < 1
    wavFilename = [];
end
if isempty(wavFilename)
    wavFilename = [PsychtoolboxRoot 'PsychDemos' filesep 'SoundFiles' filesep 'funk.wav'];
end

% Load the .wav file
[waveData, freq] = audioread(wavFilename);
waveData = waveData';               % Transpose so that each row has 1 channel
nChannels = size(waveData, 1);
nTotalFrames = size(waveData, 2);

% We'll demonstrate streaming with a 1 second buffer,
% and update the streaming buffer no faster than 100 times per second.
nBufferFrames = freq;
if (nBufferFrames > nTotalFrames)
    nBufferFrames = nTotalFrames;
end
minStreamFrames = floor(freq / 100);

% Open DATAPixx, and stop any schedules which might already be running
Datapixx('Open');
Datapixx('StopAllSchedules');
Datapixx('InitAudio');
Datapixx('SetAudioVolume', 1.00);    % Not too loud
Datapixx('RegWrRd');    % Synchronize DATAPixx registers to local register cache

% Fill the buffer with as much of the data that fits.
Datapixx('WriteAudioBuffer', waveData(:,1:nBufferFrames), 0);

% Configure the DATAPixx to play the buffer at the correct frequency.
% If the .wav file has a single channel, it will play to both ears in mono mode,
% otherwise it will play in stereo mode.
if (nChannels == 1)
    lrMode = 0;
else
    lrMode = 3;
end
Datapixx('SetAudioSchedule', 0, freq, nTotalFrames, lrMode, 0, nBufferFrames);

% Start the playback
Datapixx('StartAudioSchedule');
Datapixx('RegWrRd');    % Synchronize DATAPixx registers to local register cache

% Continuously feed the streaming buffer until the entire waveform has been played,
% or until a key is pressed.
fprintf('\nWaveform playback starting, press any key to abort.\n');
if (exist('OCTAVE_VERSION'))
    fflush(stdout);
end
nextWriteFrame = nBufferFrames + 1;
nFramesLeft = nTotalFrames - nBufferFrames;
while nFramesLeft > 0
    Datapixx('RegWrRd');   % Update registers for GetAudioStatus
    status = Datapixx('GetAudioStatus');
    if status.freeBufferFrames >= minStreamFrames           % Do not waste CPU time doing millions of tiny buffer updates
        if status.freeBufferFrames >= nFramesLeft           % Stream buffer has room for remainder of the waveform?
            nStreamFrames = nFramesLeft;                    % This iteration will download the remainder of the waveform
        else
            nStreamFrames = status.freeBufferFrames;        % Top off stream buffer with a section of waveform
        end
        Datapixx('WriteAudioBuffer', waveData(:, nextWriteFrame: nextWriteFrame+nStreamFrames-1), -1);    % Download waveData
        nextWriteFrame = nextWriteFrame + nStreamFrames;    % Update for next iteration
        nFramesLeft = nFramesLeft - nStreamFrames;
    end

    % A keypress will immediately abort the schedule
    if (KbCheck)
        Datapixx('StopAudioSchedule');
        Datapixx('RegWrRd');    % Synchronize DATAPixx registers to local register cache
        break;
    end
end

% Show final status of DAC scheduler
fprintf('\nStatus information for audio scheduler:\n');
Datapixx('RegWrRd');   % Update registers for GetAudioStatus
disp(Datapixx('GetAudioStatus'));

% Job done
Datapixx('Close');
fprintf('\nDemo completed\n\n');