188
188
unsigned int audiodevicecount = 0;
189
189
unsigned int verbosity = 4;
190
190
double yieldInterval = 0.001; // How long to wait in calls to PsychYieldIntervalSeconds().
191
psych_bool uselocking = TRUE; // Use Mutex locking and signalling code for thread synchronization?
192
psych_bool lockToCore1 = TRUE; // Lock all engine threads to run on cpu core 1 on Windows to work around broken TSC sync on multi-cores?
191
psych_bool uselocking = TRUE; // Use Mutex locking and signalling code for thread synchronization?
192
psych_bool lockToCore1 = TRUE; // NO LONGER USED: Lock all engine threads to run on cpu core 1 on Windows to work around broken TSC sync on multi-cores?
193
193
psych_bool pulseaudio_autosuspend = TRUE; // Should we try to suspend the Pulseaudio sound server on Linux while we're active?
194
194
psych_bool pulseaudio_isSuspended = FALSE; // Is PulseAudio suspended by us?
758
758
psych_int64 playposition, outsbsize, insbsize, recposition;
759
759
psych_int64 outsboffset;
760
760
unsigned int reqstate;
761
double now, firstsampleonset, onsetDelta, offsetDelta, captureStartTime, tMonotonic;
761
double now, firstsampleonset, onsetDelta, offsetDelta, captureStartTime;
762
762
double repeatCount;
763
763
psych_int64 playpositionlimit;
764
764
PaHostApiTypeId hA;
797
797
// the audio thread to cpu core 1, hope that repeated redundant
798
798
// calls don't create scheduling overhead or excessive other overhead.
799
799
// The explanation for this can be found in Source/Windows/Base/PsychTimeGlue.c
800
if (lockToCore1) SetThreadAffinityMask(GetCurrentThread(), 1);
801
// Update: We leave the decision to the time glue if we should lock to core zero,
802
// or some other usercode defined subset of cores, or all cores. PsychAutoLockThreadToCores()
803
// Update: No longer needed, as the job is done implicitely by the call to
804
// PsychGetAdjustedPrecisionTimerSeconds(&now);
806
// DISABLED: PsychAutoLockThreadToCores(NULL);
803
809
// Retrieve current system time:
820
826
// further processing.
822
828
// Get current CLOCK_MONOTONIC time:
823
tMonotonic = PsychOSGetLinuxMonotonicTime();
829
double tMonotonic = PsychOSGetLinuxMonotonicTime();
825
831
// Returned current time timestamp closer to tMonotonic than to GetSecs time?
826
832
if (fabs(timeInfo->currentTime - tMonotonic) < fabs(timeInfo->currentTime - now)) {
939
945
// sound content (ie., not simply zero silence padding frames):
940
946
committedFrames = 0;
948
// Reset number of silence frames so far:
942
951
// NULL-out pointer to buffer with sound data to play. It will get initialized later on
943
952
// in PsychPAProcessSchedule():
944
953
playoutbuffer = NULL;
966
975
// Assign 1 as neutral value for AM modulator slaves, as 1 is the neutral
967
976
// element for gain-modulation (multiplication), as opposed to zero as neutral
968
977
// element for mixing and for outputting "silence":
969
neutralValue = (dev->opmode & kPortAudioIsAMModulator) ? 1.0 : 0;
978
neutralValue = (dev->opmode & kPortAudioIsAMModulator) ? 1.0f : 0.0f;
971
980
// Requested logical playback state is "stopped" or "aborting" ? If so, abort.
972
981
if ((reqstate == 0) || (reqstate == 3)) {
988
997
PsychPAUnlockDeviceMutex(dev);
990
999
// Prime the outputbuffer with silence, so playback is effectively stopped:
991
if (outputBuffer && !isSlave) memset(outputBuffer, 0, (size_t) framesPerBuffer * outchannels * sizeof(float));
1000
if (outputBuffer && !isSlave) memset(outputBuffer, 0, (size_t) (framesPerBuffer * outchannels * sizeof(float)));
993
1002
if (dev->runMode == 0) {
994
1003
// Runmode 0: We shall really stop the engine:
1019
1028
PsychPAUnlockDeviceMutex(dev);
1021
1030
// Prime the outputbuffer with silence to simulate a stopped audio device:
1022
if (outputBuffer && !isSlave) memset(outputBuffer, 0, (size_t) framesPerBuffer * outchannels * sizeof(float));
1031
if (outputBuffer && !isSlave) memset(outputBuffer, 0, (size_t) (framesPerBuffer * outchannels * sizeof(float)));
1025
1034
return(paContinue);
1084
1093
PsychPAUnlockDeviceMutex(dev);
1086
1095
// At least one buffer away. Fill our buffer with zeros, aka silence:
1087
if (!isSlave) memset(outputBuffer, 0, (size_t) framesPerBuffer * outchannels * sizeof(float));
1096
if (!isSlave) memset(outputBuffer, 0, (size_t) (framesPerBuffer * outchannels * sizeof(float)));
1089
1098
// Ready. Tell engine to continue stream processing, i.e., call us again...
1090
1099
return(paContinue);
1097
1106
// Fill in some silence:
1098
1107
if (neutralValue == 0) {
1099
1108
// Fast-path: Zerofill for silence...
1100
memset(outputBuffer, 0, (size_t) silenceframes * outchannels * sizeof(float));
1109
memset(outputBuffer, 0, (size_t) (silenceframes * outchannels * sizeof(float)));
1101
1110
out+= (silenceframes * outchannels);
1143
1152
// Scratch buffers for slave callbacks already allocated?
1144
1153
if ((dev->opmode & kPortAudioCapture) && (dev->slaveInBuffer == NULL)) {
1145
1154
// Allocate input distribution buffer:
1146
dev->slaveInBuffer = (float*) malloc(sizeof(float) * dev->batchsize * inchannels);
1155
dev->slaveInBuffer = (float*) malloc(sizeof(float) * (size_t) (dev->batchsize * inchannels));
1147
1156
if (NULL == dev->slaveInBuffer) {
1148
1157
// Out of memory! Perform an emergency abort:
1149
1158
dev->reqstate = 255;
1157
1166
if ((dev->opmode & kPortAudioPlayBack) && (dev->slaveOutBuffer == NULL)) {
1158
1167
// Allocate output receive buffer and output gain receive buffer:
1159
dev->slaveOutBuffer = (float*) malloc(sizeof(float) * dev->batchsize * outchannels);
1160
dev->slaveGainBuffer = (float*) malloc(sizeof(float) * dev->batchsize * outchannels);
1168
dev->slaveOutBuffer = (float*) malloc(sizeof(float) * (size_t) (dev->batchsize * outchannels));
1169
dev->slaveGainBuffer = (float*) malloc(sizeof(float) * (size_t) (dev->batchsize * outchannels));
1161
1170
if ((NULL == dev->slaveOutBuffer) || (NULL == dev->slaveGainBuffer)) {
1162
1171
// Out of memory! Perform an emergency abort:
1163
1172
dev->reqstate = 255;
1171
1180
// Have scratch buffers ready. Clear output intermix buffer:
1172
memset(outputBuffer, 0, dev->batchsize * outchannels * sizeof(float));
1181
memset(outputBuffer, 0, (size_t) (dev->batchsize * outchannels * sizeof(float)));
1174
1183
// Iterate over all slave device callbacks: Or at least until all registered slaves are handled.
1175
1184
numSlavesHandled = 0;
1357
1366
// This code only executes on non-masters in live monitoring mode - a mode where all
1358
1367
// sound data is fed back immediately with shortest possible latency
1359
1368
// from input to output, without any involvement of Matlab/Octave code:
1369
// Note: "Non-master" also means: A standard sound device without any slaves!
1360
1370
if (!isMaster && (dev->opmode & kPortAudioMonitoring)) {
1361
1371
// Copy input buffer to output buffer:
1362
memcpy(out, &(in[committedFrames * inchannels]), framesPerBuffer * outchannels * sizeof(float));
1372
// We need to offset our copy by committedFrames into the "in"putbuffer.
1373
// Reason: committedFrames output buffer frames have been filled with
1374
// silence already, and framesPerBuffer has been decremented by these
1375
// committedFrames - We can only copy this reduced amount from the input
1376
// buffer to the output buffer. We choose the most recent 'framesPerBuffer'
1377
// frames from the inputbuffer, ie., at offset committedFrames, because the
1378
// freshest frames are towards the end of the buffer, not at the beginning.
1379
// (Yes this may twist your mind, but it makes sense, given the way the buffers
1380
// are filled during capture and emptied during playback, believe me!)
1381
memcpy(out, &(in[committedFrames * inchannels]), (size_t) (framesPerBuffer * outchannels * sizeof(float)));
1364
1383
// Store updated positions in device structure:
1365
1384
dev->playposition = playposition + (framesPerBuffer * outchannels);
1484
1503
// Store updated playposition in device structure:
1485
1504
dev->playposition = playposition;
1487
// Update total count of emitted valid non-silence sample frames:
1506
// Update total count of emitted sample frames during this callback by number of non-silence frames:
1488
1507
committedFrames += i / outchannels;
1490
1509
// Compute output time of last outputted sample from this iteration:
1491
1510
dev->currentTime = firstsampleonset + ((double) committedFrames / (double) dev->streaminfo->sampleRate);
1493
1512
// Update total count of emitted samples since start of playback:
1494
dev->totalplaycount+= committedFrames * outchannels;
1513
dev->totalplaycount+= (committedFrames - silenceframes) * outchannels;
1496
1515
// Another end-of-playback check:
1497
1516
if (parc > 0) {
1824
1843
pa_initialized = FALSE;
1846
// Detach our callback function for low-level debug output:
1847
PaUtil_SetDebugPrintFunction(NULL);
1827
1849
// Restart suspended PulseAudio server if it was suspended by us:
1828
1850
if (pulseaudio_isSuspended) {
1829
1851
// Call external "pactl" utility via shell to ask
1873
1892
#if PSYCH_SYSTEM == PSYCH_WINDOWS
1874
// Sanity check dynamic portaudio_x86.dll loading on Windows:
1875
if (NULL == LoadLibrary("portaudio_x86.dll")) {
1893
// Sanity check dynamic portaudio dll loading on Windows:
1894
if ((NULL == LoadLibrary("portaudio_x86.dll")) && (NULL == LoadLibrary("portaudio_x64.dll"))) {
1877
1896
printf("\n\nPTB-ERROR: Tried to initialize PsychPortAudio's PortAudio engine. This didn't work,\n");
1878
printf("PTB-ERROR: because i couldn't find or load the required portaudio_x86.dll library.\n");
1897
printf("PTB-ERROR: because i couldn't find or load the required portaudio_x86.dll or portaudio_x64.dll library.\n");
1879
1898
printf("PTB-ERROR: Please make sure to call the InitializePsychSound function before first use of\n");
1880
1899
printf("PTB-ERROR: PsychPortAudio, otherwise this error will happen.\n\n");
1881
PsychErrorExitMsg(PsychError_user, "Failed to initialize due to portaudio_x86.dll loading problem. Call InitializePsychSound first! Aborted.");
1900
PsychErrorExitMsg(PsychError_user, "Failed to initialize due to portaudio DLL loading problem. Call InitializePsychSound first! Aborted.");
1888
1907
if ((err=Pa_Initialize())!=paNoError) {
1889
1908
printf("PTB-ERROR: Portaudio initialization failed with following port audio error: %s \n", Pa_GetErrorText(err));
1909
PaUtil_SetDebugPrintFunction(NULL);
1890
1910
PsychErrorExitMsg(PsychError_system, "Failed to initialize PortAudio subsystem.");
1993
2013
double* mychannelmap;
1994
2014
double suggestedLatency, lowlatency;
1995
PaDeviceIndex paDevice;
1996
2015
PaHostApiIndex paHostAPI;
1997
2016
PaStreamParameters outputParameters;
1998
2017
PaStreamParameters inputParameters;
2248
2267
// No specific frequency requested:
2249
2268
if (latencyclass < 3) {
2250
2269
// At levels < 3, we select the device specific default.
2251
freq = referenceDevInfo->defaultSampleRate;
2270
freq = (int) referenceDevInfo->defaultSampleRate;
2254
2273
freq = 96000; // Go really high...
2403
2422
if (mode & kPortAudioPlayBack) {
2404
2423
// Allocate a dummy outputbuffer with one sampleframe:
2405
2424
audiodevices[audiodevicecount].outputbuffersize = sizeof(float) * audiodevices[audiodevicecount].outchannels * 1;
2406
audiodevices[audiodevicecount].outputbuffer = (float*) malloc(audiodevices[audiodevicecount].outputbuffersize);
2425
audiodevices[audiodevicecount].outputbuffer = (float*) malloc((size_t) audiodevices[audiodevicecount].outputbuffersize);
2407
2426
if (audiodevices[audiodevicecount].outputbuffer==NULL) PsychErrorExitMsg(PsychError_outofMemory, "Out of system memory when trying to allocate audio buffer.");
2410
2429
if (mode & kPortAudioCapture) {
2411
2430
// Allocate a dummy inputbuffer with one sampleframe:
2412
2431
audiodevices[audiodevicecount].inputbuffersize = sizeof(float) * audiodevices[audiodevicecount].inchannels * 1;
2413
audiodevices[audiodevicecount].inputbuffer = (float*) calloc(1, audiodevices[audiodevicecount].inputbuffersize);
2432
audiodevices[audiodevicecount].inputbuffer = (float*) calloc(1, (size_t) audiodevices[audiodevicecount].inputbuffersize);
2414
2433
if (audiodevices[audiodevicecount].inputbuffer == NULL) PsychErrorExitMsg(PsychError_outofMemory, "Free system memory exhausted when trying to allocate audio recording buffer!");
2604
2623
PsychAllocInIntegerListArg(3, kPsychArgOptional, &numel, &nrchannels);
2605
2624
if (numel == 0) {
2606
2625
// No optional channelcount argument provided: Default to pamaster settings:
2607
mynrchannels[0] = audiodevices[pamaster].outchannels;
2608
mynrchannels[1] = audiodevices[pamaster].inchannels;
2609
if (mode & kPortAudioIsOutputCapture) mynrchannels[1] = audiodevices[pamaster].outchannels;
2626
mynrchannels[0] = (int) audiodevices[pamaster].outchannels;
2627
mynrchannels[1] = (int) audiodevices[pamaster].inchannels;
2628
if (mode & kPortAudioIsOutputCapture) mynrchannels[1] = (int) audiodevices[pamaster].outchannels;
2611
2630
else if (numel == 1) {
2612
2631
// One argument provided: Set same count for playback and recording:
2786
2805
// Setup per-channel output volumes for slave: Each channel starts with a 1.0 setting, ie., max volume:
2787
2806
if (audiodevices[audiodevicecount].outchannels > 0) {
2788
audiodevices[audiodevicecount].outChannelVolumes = (float*) malloc(sizeof(float) * audiodevices[audiodevicecount].outchannels);
2807
audiodevices[audiodevicecount].outChannelVolumes = (float*) malloc(sizeof(float) * (size_t) audiodevices[audiodevicecount].outchannels);
2789
2808
if (audiodevices[audiodevicecount].outChannelVolumes == NULL) PsychErrorExitMsg(PsychError_outofMemory, "Memory exhausted during audio volume vector allocation.");
2790
2809
for (i = 0; i < audiodevices[audiodevicecount].outchannels; i++) audiodevices[audiodevicecount].outChannelVolumes[i] = 1.0;
3030
3049
PsychPAUnlockDeviceMutex(&audiodevices[pahandle]);
3032
3051
// Ok, everything sane, fill the buffer:
3033
buffersize = sizeof(float) * inchannels * insamples;
3052
buffersize = sizeof(float) * (size_t) (inchannels * insamples);
3034
3053
if (audiodevices[pahandle].outputbuffer && (audiodevices[pahandle].outputbuffersize != buffersize)) {
3035
3054
free(audiodevices[pahandle].outputbuffer);
3036
3055
audiodevices[pahandle].outputbuffer = NULL;
3100
3119
if (audiodevices[pahandle].outputbuffer == NULL) PsychErrorExitMsg(PsychError_user, "No audio buffer allocated! You must call this method once before start of playback to initially allocate a buffer of sufficient size.");
3102
3121
// Buffer of sufficient size for a streaming refill of this amount?
3103
buffersize = sizeof(float) * (psych_int64) inchannels * (psych_int64) insamples;
3104
if (audiodevices[pahandle].outputbuffersize < buffersize) PsychErrorExitMsg(PsychError_user, "Total capacity of audio buffer is too small for a refill of this size! Allocate an initial buffer of at least the size of the biggest refill.");
3122
buffersize = sizeof(float) * (size_t) ((psych_int64) inchannels * (psych_int64) insamples);
3123
if (audiodevices[pahandle].outputbuffersize < (psych_int64) buffersize) PsychErrorExitMsg(PsychError_user, "Total capacity of audio buffer is too small for a refill of this size! Allocate an initial buffer of at least the size of the biggest refill.");
3106
3125
// Need to lock b'cause of 'playposition':
3107
3126
PsychPALockDeviceMutex(&audiodevices[pahandle]);
3329
3348
if (bufferhandle > 0) {
3330
3349
// Generic buffer:
3331
3350
outdata = buffer->outputbuffer;
3332
outbuffersize = buffer->outputbuffersize;
3351
outbuffersize = (size_t) buffer->outputbuffersize;
3335
3354
// Standard playout buffer:
3336
3355
outdata = audiodevices[pahandle].outputbuffer;
3337
outbuffersize = audiodevices[pahandle].outputbuffersize;
3356
outbuffersize = (size_t) audiodevices[pahandle].outputbuffersize;
3340
3359
// Buffer exists?
3529
3548
// Deref bufferHandle:
3530
3549
buffer = PsychPAGetAudioBuffer(bufferhandle);
3531
3550
outdata = buffer->outputbuffer;
3532
outbuffersize = buffer->outputbuffersize;
3551
outbuffersize = (size_t) buffer->outputbuffersize;
3533
3552
buffersize = sizeof(float) * (size_t) inchannels * (size_t) insamples;
3632
3651
if (pahandle < 0 || pahandle>=MAX_PSYCH_AUDIO_DEVS || audiodevices[pahandle].stream == NULL) PsychErrorExitMsg(PsychError_user, "Invalid audio device handle provided.");
3633
3652
if ((audiodevices[pahandle].opmode & kPortAudioCapture) == 0) PsychErrorExitMsg(PsychError_user, "Audio device has not been opened for audio capture, so this call doesn't make sense.");
3635
buffersize = audiodevices[pahandle].inputbuffersize;
3654
buffersize = (size_t) audiodevices[pahandle].inputbuffersize;
3637
3656
// Copy in optional amount of buffer memory to allocate for internal recording ringbuffer:
3673
3692
// Calculate needed buffersize in samples: Convert allocsize in seconds to size in bytes:
3674
3693
audiodevices[pahandle].inputbuffersize = sizeof(float) * ((psych_int64) (allocsize * audiodevices[pahandle].streaminfo->sampleRate)) * audiodevices[pahandle].inchannels;
3675
audiodevices[pahandle].inputbuffer = (float*) calloc(1, audiodevices[pahandle].inputbuffersize);
3694
audiodevices[pahandle].inputbuffer = (float*) calloc(1, (size_t) audiodevices[pahandle].inputbuffersize);
3676
3695
if (audiodevices[pahandle].inputbuffer == NULL) PsychErrorExitMsg(PsychError_outofMemory, "Free system memory exhausted when trying to allocate audio recording buffer!");
3678
3697
// This was an (re-)allocation call, so no data is pending in the buffer.
3711
3730
minSamples = minSecs * ((double) audiodevices[pahandle].streaminfo->sampleRate) * ((double) audiodevices[pahandle].inchannels) + ((double) audiodevices[pahandle].inchannels);
3713
3732
// Bigger than buffersize? That would be a no no...
3714
if (((psych_int64) minSamples * sizeof(float)) > audiodevices[pahandle].inputbuffersize) {
3733
if (((psych_int64) (minSamples * sizeof(float))) > audiodevices[pahandle].inputbuffersize) {
3715
3734
PsychPAUnlockDeviceMutex(&audiodevices[pahandle]);
3716
3735
PsychErrorExitMsg(PsychError_user, "Invalid 'minimumAmountToReturnSecs' parameter: The requested minimum is bigger than the whole capture buffer size!'");
3752
3771
PsychPAUnlockDeviceMutex(&audiodevices[pahandle]);
3754
3773
insamples = (insamples < 0) ? 0 : insamples;
3755
buffersize = insamples * sizeof(float);
3774
buffersize = (size_t) insamples * sizeof(float);
3757
3776
// Buffer "overflow" detected?
3758
if (buffersize > audiodevices[pahandle].inputbuffersize) {
3777
if ((psych_int64) buffersize > audiodevices[pahandle].inputbuffersize) {
3759
3778
// Ok, the buffer did overrun and captured data was lost. Limit returned data
3760
3779
// to buffersize and set the overrun flag, optionally output a warning:
3761
buffersize = audiodevices[pahandle].inputbuffersize;
3780
buffersize = (size_t) audiodevices[pahandle].inputbuffersize;
3762
3781
insamples = buffersize / sizeof(float);
3764
3783
// Set overrun flag:
3774
3793
// Clamp insamples to that value, if neccessary:
3775
3794
if (insamples > maxSamples) {
3776
3795
insamples = maxSamples;
3777
buffersize = insamples * sizeof(float);
3796
buffersize = (size_t) insamples * sizeof(float);
4578
4596
PsychSetStructArrayDoubleElement("XRuns", 0, audiodevices[pahandle].xruns, status);
4579
4597
PsychSetStructArrayDoubleElement("TotalCalls", 0, audiodevices[pahandle].paCalls, status);
4580
4598
PsychSetStructArrayDoubleElement("TimeFailed", 0, audiodevices[pahandle].noTime, status);
4581
PsychSetStructArrayDoubleElement("BufferSize", 0, audiodevices[pahandle].batchsize, status);
4599
PsychSetStructArrayDoubleElement("BufferSize", 0, (double) audiodevices[pahandle].batchsize, status);
4582
4600
PsychSetStructArrayDoubleElement("CPULoad", 0, (Pa_IsStreamActive(audiodevices[pahandle].stream)) ? Pa_GetStreamCpuLoad(audiodevices[pahandle].stream) : 0.0, status);
4583
4601
PsychSetStructArrayDoubleElement("PredictedLatency", 0, audiodevices[pahandle].predictedLatency, status);
4584
4602
PsychSetStructArrayDoubleElement("LatencyBias", 0, audiodevices[pahandle].latencyBias, status);
5041
5059
if (endSample > maxSample) PsychErrorExitMsg(PsychError_user, "Invalid 'endSample' provided. Must be no greater than total buffersize!");
5044
endSample = maxSample;
5062
endSample = (double) maxSample;
5047
5065
if (endSample < startSample) PsychErrorExitMsg(PsychError_user, "Invalid 'endSample' provided. Must be greater or equal than 'startSample'!");
5075
5093
"potential race-conditions between internal processing threads. Locking is enabled by default. Only "
5076
5094
"disable locking to work around seriously broken audio device drivers or system setups and be aware "
5077
5095
"that this may have unpleasant side effects and can cause all kinds of malfunctions by itself!\n"
5078
"'lockToCore1' - Enable (1) or Disable (0) locking of all audio engine processing threads to cpu core 1 "
5096
"'lockToCore1' - Deprecated: Enable (1) or Disable (0) locking of all audio engine processing threads to cpu core 1 "
5079
5097
"on Microsoft Windows systems. By default threads are locked to cpu core 1 to avoid problems with "
5080
5098
"timestamping due to bugs in some microprocessors clocks and in Microsoft Windows itself. If you're "
5081
5099
"confident/certain that your system is bugfree wrt. to its clocks and want to get a bit more "
5082
5100
"performance out of multi-core machines, you can disable this. You must perform this setting before "
5083
"you open the first audio device the first time, otherwise the setting might be ignored.\n"
5101
"you open the first audio device the first time, otherwise the setting might be ignored. In the current "
5102
"driver this setting is silently ignored, as a new method of handling this has been implemented.\n"
5084
5103
"'audioserver_autosuspend' - Enable (1) or Disable (0) automatic suspending of running desktop "
5085
5104
"audio servers, e.g., PulseAudio, while PsychPortAudio is active. Default is (1) - suspend while "
5086
5105
"PsychPortAudio does its thing. Desktop sound servers like the commonly used PulseAudio server "
5429
5448
if (endSample > maxSample) PsychErrorExitMsg(PsychError_user, "Invalid 'endSample' provided. Must be no greater than total buffersize!");
5432
endSample = maxSample;
5451
endSample = (double) maxSample;
5435
5454
if (endSample < startSample) PsychErrorExitMsg(PsychError_user, "Invalid 'endSample' provided. Must be greater or equal than 'startSample'!");
5452
5471
slot->mode = 1 | 2 | ((specialFlags & 1) ? 4 : 0);
5453
5472
slot->bufferhandle = bufferHandle;
5454
5473
slot->repetitions = (commandCode == 0) ? ((repetitions == 0) ? -1 : repetitions) : 0.0;;
5455
slot->loopStartFrame = startSample;
5456
slot->loopEndFrame = endSample;
5474
slot->loopStartFrame = (psych_int64) startSample;
5475
slot->loopEndFrame = (psych_int64) endSample;
5457
5476
slot->command = commandCode;
5458
5477
slot->tWhen = (commandCode > 0) ? repetitions : 0.0;