mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
This commit is contained in:
parent
dfcf3293e5
commit
ec4c0a5985
6 changed files with 397 additions and 444 deletions
|
|
@ -140,13 +140,11 @@ public:
|
|||
|
||||
int count = 0;
|
||||
int i;
|
||||
for (i = maxNumChans; --i >= 0;)
|
||||
if (activeInputChans[i])
|
||||
tempInputBuffers[i] = audioBuffer + count++ * numSamples;
|
||||
for (i = 0; i < numInputChans; ++i)
|
||||
tempInputBuffers[i] = audioBuffer + count++ * numSamples;
|
||||
|
||||
for (i = maxNumChans; --i >= 0;)
|
||||
if (activeOutputChans[i])
|
||||
tempOutputBuffers[i] = audioBuffer + count++ * numSamples;
|
||||
for (i = 0; i < numOutputChans; ++i)
|
||||
tempOutputBuffers[i] = audioBuffer + count++ * numSamples;
|
||||
}
|
||||
|
||||
// returns the number of actual available channels
|
||||
|
|
@ -424,8 +422,17 @@ public:
|
|||
|
||||
activeInputChans = inputChannels;
|
||||
activeOutputChans = outputChannels;
|
||||
numInputChans = inputChannels.countNumberOfSetBits();
|
||||
numOutputChans = outputChannels.countNumberOfSetBits();
|
||||
|
||||
activeInputChans.setRange (inChanNames.size(),
|
||||
activeInputChans.getHighestBit() + 1 - inChanNames.size(),
|
||||
false);
|
||||
|
||||
activeOutputChans.setRange (outChanNames.size(),
|
||||
activeOutputChans.getHighestBit() + 1 - outChanNames.size(),
|
||||
false);
|
||||
|
||||
numInputChans = activeInputChans.countNumberOfSetBits();
|
||||
numOutputChans = activeOutputChans.countNumberOfSetBits();
|
||||
|
||||
// set sample rate
|
||||
Float64 sr = newSampleRate;
|
||||
|
|
@ -461,17 +468,6 @@ public:
|
|||
if (bufferSizes.size() == 0)
|
||||
error = "Device has no available buffer-sizes";
|
||||
|
||||
numInputChans = jmin (numInputChans, numInputChannelInfos);
|
||||
numOutputChans = jmin (numOutputChans, numOutputChannelInfos);
|
||||
|
||||
activeInputChans.setRange (inChanNames.size(),
|
||||
activeInputChans.getHighestBit() + 1 - inChanNames.size(),
|
||||
false);
|
||||
|
||||
activeOutputChans.setRange (outChanNames.size(),
|
||||
activeOutputChans.getHighestBit() + 1 - outChanNames.size(),
|
||||
false);
|
||||
|
||||
if (inputDevice != 0 && error.isEmpty())
|
||||
error = inputDevice->reopen (inputChannels,
|
||||
outputChannels,
|
||||
|
|
@ -703,7 +699,9 @@ public:
|
|||
const bool thisIsInput = inChanNames.size() > 0 && outChanNames.size() == 0;
|
||||
const bool otherIsInput = result->inChanNames.size() > 0 && result->outChanNames.size() == 0;
|
||||
|
||||
if (thisIsInput != otherIsInput)
|
||||
if (thisIsInput != otherIsInput
|
||||
|| (inChanNames.size() + outChanNames.size() == 0)
|
||||
|| (result->inChanNames.size() + result->outChanNames.size()) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -113,18 +113,10 @@ static void logError (const String& context, long error)
|
|||
|
||||
//==============================================================================
|
||||
class ASIOAudioIODevice;
|
||||
static ASIOAudioIODevice* volatile currentASIODev = 0;
|
||||
|
||||
static IASIO* volatile asioObject = 0;
|
||||
static ASIOAudioIODevice* volatile currentASIODev[3] = { 0, 0, 0 };
|
||||
|
||||
static const int maxASIOChannels = 160;
|
||||
|
||||
static ASIOCallbacks callbacks;
|
||||
static ASIOBufferInfo bufferInfos[64];
|
||||
|
||||
static bool volatile insideControlPanelModalLoop = false;
|
||||
static bool volatile shouldUsePreferredSize = false;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class JUCE_API ASIOAudioIODevice : public AudioIODevice,
|
||||
|
|
@ -134,47 +126,42 @@ class JUCE_API ASIOAudioIODevice : public AudioIODevice,
|
|||
public:
|
||||
Component ourWindow;
|
||||
|
||||
ASIOAudioIODevice (const String& name_, CLSID classId_)
|
||||
ASIOAudioIODevice (const String& name_, const CLSID classId_, const int slotNumber)
|
||||
: AudioIODevice (name_, T("ASIO")),
|
||||
Thread ("Juce ASIO"),
|
||||
asioObject (0),
|
||||
classId (classId_),
|
||||
currentBitDepth (16),
|
||||
currentSampleRate (0),
|
||||
tempBuffer (0),
|
||||
isOpen_ (false),
|
||||
isStarted (false),
|
||||
postOutput (true)
|
||||
postOutput (true),
|
||||
insideControlPanelModalLoop (false),
|
||||
shouldUsePreferredSize (false)
|
||||
{
|
||||
name = name_;
|
||||
|
||||
ourWindow.addToDesktop (0);
|
||||
windowHandle = ourWindow.getWindowHandle();
|
||||
|
||||
jassert (currentASIODev == 0);
|
||||
currentASIODev = this;
|
||||
shouldUseThread = false;
|
||||
jassert (currentASIODev [slotNumber] == 0);
|
||||
currentASIODev [slotNumber] = this;
|
||||
|
||||
openDevice();
|
||||
}
|
||||
|
||||
~ASIOAudioIODevice()
|
||||
{
|
||||
jassert (currentASIODev == this);
|
||||
if (currentASIODev == this)
|
||||
currentASIODev = 0;
|
||||
for (int i = 0; i < numElementsInArray (currentASIODev); ++i)
|
||||
if (currentASIODev[i] == this)
|
||||
currentASIODev[i] = 0;
|
||||
|
||||
close();
|
||||
log ("ASIO - exiting");
|
||||
removeCurrentDriver();
|
||||
|
||||
juce_free (tempBuffer);
|
||||
|
||||
if (isUsingThread)
|
||||
{
|
||||
signalThreadShouldExit();
|
||||
event1.signal();
|
||||
stopThread (3000);
|
||||
}
|
||||
}
|
||||
|
||||
void updateSampleRates()
|
||||
|
|
@ -314,6 +301,8 @@ public:
|
|||
currentBlockSizeSamples = bufferSizeSamples;
|
||||
currentChansOut.clear();
|
||||
currentChansIn.clear();
|
||||
zeromem (inBuffers, sizeof (inBuffers));
|
||||
zeromem (outBuffers, sizeof (outBuffers));
|
||||
|
||||
updateSampleRates();
|
||||
|
||||
|
|
@ -429,7 +418,7 @@ public:
|
|||
|
||||
ASIOBufferInfo* info = bufferInfos;
|
||||
int i;
|
||||
for (i = 0; i < numInputs; ++i)
|
||||
for (i = 0; i < totalNumInputChans; ++i)
|
||||
{
|
||||
if (inputChannels[i])
|
||||
{
|
||||
|
|
@ -442,7 +431,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < numOutputs; ++i)
|
||||
for (i = 0; i < totalNumOutputChans; ++i)
|
||||
{
|
||||
if (outputChannels[i])
|
||||
{
|
||||
|
|
@ -457,10 +446,30 @@ public:
|
|||
|
||||
const int totalBuffers = numActiveInputChans + numActiveOutputChans;
|
||||
|
||||
callbacks.bufferSwitch = &bufferSwitchCallback;
|
||||
callbacks.sampleRateDidChange = &sampleRateChangedCallback;
|
||||
callbacks.asioMessage = &asioMessagesCallback;
|
||||
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback;
|
||||
|
||||
if (currentASIODev[0] == this)
|
||||
{
|
||||
callbacks.bufferSwitch = &bufferSwitchCallback0;
|
||||
callbacks.asioMessage = &asioMessagesCallback0;
|
||||
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0;
|
||||
}
|
||||
else if (currentASIODev[1] == this)
|
||||
{
|
||||
callbacks.bufferSwitch = &bufferSwitchCallback1;
|
||||
callbacks.asioMessage = &asioMessagesCallback1;
|
||||
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1;
|
||||
}
|
||||
else if (currentASIODev[2] == this)
|
||||
{
|
||||
callbacks.bufferSwitch = &bufferSwitchCallback2;
|
||||
callbacks.asioMessage = &asioMessagesCallback2;
|
||||
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2;
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse
|
||||
}
|
||||
|
||||
log ("disposing buffers");
|
||||
err = asioObject->disposeBuffers();
|
||||
|
|
@ -497,11 +506,11 @@ public:
|
|||
Array <int> types;
|
||||
currentBitDepth = 16;
|
||||
|
||||
for (i = 0; i < jmin (numInputs, maxASIOChannels); ++i)
|
||||
for (i = 0; i < jmin (totalNumInputChans, maxASIOChannels); ++i)
|
||||
{
|
||||
if (inputChannels[i])
|
||||
{
|
||||
inBuffers[i] = tempBuffer + (currentBlockSizeSamples * n++);
|
||||
inBuffers[n] = tempBuffer + (currentBlockSizeSamples * n);
|
||||
|
||||
ASIOChannelInfo channelInfo;
|
||||
zerostruct (channelInfo);
|
||||
|
|
@ -512,24 +521,25 @@ public:
|
|||
|
||||
types.addIfNotAlreadyThere (channelInfo.type);
|
||||
typeToFormatParameters (channelInfo.type,
|
||||
inputChannelBitDepths[i],
|
||||
inputChannelBytesPerSample[i],
|
||||
inputChannelIsFloat[i],
|
||||
inputChannelLittleEndian[i]);
|
||||
inputChannelBitDepths[n],
|
||||
inputChannelBytesPerSample[n],
|
||||
inputChannelIsFloat[n],
|
||||
inputChannelLittleEndian[n]);
|
||||
|
||||
currentBitDepth = jmax (currentBitDepth, inputChannelBitDepths[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
inBuffers[i] = 0;
|
||||
currentBitDepth = jmax (currentBitDepth, inputChannelBitDepths[n]);
|
||||
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < jmin (numOutputs, maxASIOChannels); ++i)
|
||||
jassert (numActiveInputChans == n);
|
||||
n = 0;
|
||||
|
||||
for (i = 0; i < jmin (totalNumOutputChans, maxASIOChannels); ++i)
|
||||
{
|
||||
if (outputChannels[i])
|
||||
{
|
||||
outBuffers[i] = tempBuffer + (currentBlockSizeSamples * n++);
|
||||
outBuffers[n] = tempBuffer + (currentBlockSizeSamples * (numActiveInputChans + n));
|
||||
|
||||
ASIOChannelInfo channelInfo;
|
||||
zerostruct (channelInfo);
|
||||
|
|
@ -540,19 +550,19 @@ public:
|
|||
|
||||
types.addIfNotAlreadyThere (channelInfo.type);
|
||||
typeToFormatParameters (channelInfo.type,
|
||||
outputChannelBitDepths[i],
|
||||
outputChannelBytesPerSample[i],
|
||||
outputChannelIsFloat[i],
|
||||
outputChannelLittleEndian[i]);
|
||||
outputChannelBitDepths[n],
|
||||
outputChannelBytesPerSample[n],
|
||||
outputChannelIsFloat[n],
|
||||
outputChannelLittleEndian[n]);
|
||||
|
||||
currentBitDepth = jmax (currentBitDepth, outputChannelBitDepths[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
outBuffers[i] = 0;
|
||||
currentBitDepth = jmax (currentBitDepth, outputChannelBitDepths[n]);
|
||||
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
jassert (numActiveOutputChans == n);
|
||||
|
||||
for (i = types.size(); --i >= 0;)
|
||||
{
|
||||
log (T("channel format: ") + String (types[i]));
|
||||
|
|
@ -560,30 +570,22 @@ public:
|
|||
|
||||
jassert (n <= totalBuffers);
|
||||
|
||||
n = numActiveInputChans;
|
||||
for (i = 0; i < numOutputs; ++i)
|
||||
for (i = 0; i < numActiveOutputChans; ++i)
|
||||
{
|
||||
if (outputChannels[i])
|
||||
const int size = currentBlockSizeSamples * (outputChannelBitDepths[i] >> 3);
|
||||
|
||||
if (bufferInfos [numActiveInputChans + i].buffers[0] == 0
|
||||
|| bufferInfos [numActiveInputChans + i].buffers[1] == 0)
|
||||
{
|
||||
const int size = currentBlockSizeSamples * (outputChannelBitDepths[i] >> 3);
|
||||
|
||||
if (bufferInfos[n].buffers[0] == 0
|
||||
|| bufferInfos[n].buffers[1] == 0)
|
||||
{
|
||||
log ("!! Null buffers");
|
||||
}
|
||||
else
|
||||
{
|
||||
zeromem (bufferInfos[n].buffers[0], size);
|
||||
zeromem (bufferInfos[n].buffers[1], size);
|
||||
}
|
||||
|
||||
++n;
|
||||
log ("!! Null buffers");
|
||||
}
|
||||
else
|
||||
{
|
||||
zeromem (bufferInfos[numActiveInputChans + i].buffers[0], size);
|
||||
zeromem (bufferInfos[numActiveInputChans + i].buffers[1], size);
|
||||
}
|
||||
}
|
||||
|
||||
jassert (n <= totalBuffers);
|
||||
|
||||
inputLatency = outputLatency = 0;
|
||||
|
||||
if (asioObject->getLatencies (&inputLatency, &outputLatency) != 0)
|
||||
|
|
@ -601,56 +603,32 @@ public:
|
|||
isOpen_ = true;
|
||||
isThreadReady = false;
|
||||
|
||||
if (isUsingThread)
|
||||
{
|
||||
event1.wait (1); // reset the event in case it was flipped by a callback from the ASIO->start call in openDevice()
|
||||
startThread (8);
|
||||
log ("starting ASIO");
|
||||
calledback = false;
|
||||
err = asioObject->start();
|
||||
|
||||
int count = 5000;
|
||||
while (--count > 0 && ! isThreadReady)
|
||||
sleep (1);
|
||||
}
|
||||
|
||||
if (isUsingThread && ! isThreadRunning())
|
||||
if (err != 0)
|
||||
{
|
||||
error = "Can't start thread!";
|
||||
isOpen_ = false;
|
||||
log ("ASIO - stop on failure");
|
||||
Thread::sleep (10);
|
||||
asioObject->stop();
|
||||
error = "Can't start device";
|
||||
Thread::sleep (10);
|
||||
}
|
||||
else
|
||||
{
|
||||
log ("starting ASIO");
|
||||
calledback = false;
|
||||
err = asioObject->start();
|
||||
|
||||
if (err != 0)
|
||||
{
|
||||
if (isUsingThread)
|
||||
{
|
||||
signalThreadShouldExit();
|
||||
event1.signal();
|
||||
stopThread (3000);
|
||||
}
|
||||
|
||||
isOpen_ = false;
|
||||
log ("ASIO - stop on failure");
|
||||
int count = 300;
|
||||
while (--count > 0 && ! calledback)
|
||||
Thread::sleep (10);
|
||||
|
||||
isStarted = true;
|
||||
|
||||
if (! calledback)
|
||||
{
|
||||
error = "Device didn't start correctly";
|
||||
log ("ASIO didn't callback - stopping..");
|
||||
asioObject->stop();
|
||||
error = "Can't start device";
|
||||
Thread::sleep (10);
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = 300;
|
||||
while (--count > 0 && ! calledback)
|
||||
Thread::sleep (10);
|
||||
|
||||
isStarted = true;
|
||||
|
||||
if (! calledback)
|
||||
{
|
||||
error = "Device didn't start correctly";
|
||||
log ("ASIO didn't callback - stopping..");
|
||||
asioObject->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -694,13 +672,6 @@ public:
|
|||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
|
||||
if (isUsingThread)
|
||||
{
|
||||
signalThreadShouldExit();
|
||||
event1.signal();
|
||||
stopThread (3000);
|
||||
}
|
||||
|
||||
isOpen_ = false;
|
||||
isStarted = false;
|
||||
needToReset = false;
|
||||
|
|
@ -786,9 +757,7 @@ public:
|
|||
|
||||
bool isPlaying()
|
||||
{
|
||||
return isASIOOpen
|
||||
&& (isThreadRunning() || ! isUsingThread)
|
||||
&& (currentCallback != 0);
|
||||
return isASIOOpen && (currentCallback != 0);
|
||||
}
|
||||
|
||||
const String getLastError()
|
||||
|
|
@ -796,11 +765,6 @@ public:
|
|||
return error;
|
||||
}
|
||||
|
||||
void setUsingThread (bool b)
|
||||
{
|
||||
shouldUseThread = b;
|
||||
}
|
||||
|
||||
bool hasControlPanel() const
|
||||
{
|
||||
return true;
|
||||
|
|
@ -907,12 +871,15 @@ public:
|
|||
|
||||
private:
|
||||
//==============================================================================
|
||||
IASIO* volatile asioObject;
|
||||
ASIOCallbacks callbacks;
|
||||
|
||||
void* windowHandle;
|
||||
CLSID classId;
|
||||
String error;
|
||||
|
||||
long numInputs, numOutputs;
|
||||
StringArray outputChannelNames, inputChannelNames;
|
||||
long totalNumInputChans, totalNumOutputChans;
|
||||
StringArray inputChannelNames, outputChannelNames;
|
||||
|
||||
Array<int> sampleRates, bufferSizes;
|
||||
long inputLatency, outputLatency;
|
||||
|
|
@ -925,30 +892,33 @@ private:
|
|||
AudioIODeviceCallback* volatile currentCallback;
|
||||
CriticalSection callbackLock;
|
||||
|
||||
float* inBuffers[maxASIOChannels];
|
||||
float* outBuffers[maxASIOChannels];
|
||||
int inputChannelBitDepths[maxASIOChannels];
|
||||
int outputChannelBitDepths[maxASIOChannels];
|
||||
int inputChannelBytesPerSample[maxASIOChannels];
|
||||
int outputChannelBytesPerSample[maxASIOChannels];
|
||||
bool inputChannelIsFloat[maxASIOChannels];
|
||||
bool outputChannelIsFloat[maxASIOChannels];
|
||||
bool inputChannelLittleEndian[maxASIOChannels];
|
||||
bool outputChannelLittleEndian[maxASIOChannels];
|
||||
ASIOBufferInfo bufferInfos [maxASIOChannels];
|
||||
float* inBuffers [maxASIOChannels];
|
||||
float* outBuffers [maxASIOChannels];
|
||||
|
||||
int inputChannelBitDepths [maxASIOChannels];
|
||||
int outputChannelBitDepths [maxASIOChannels];
|
||||
int inputChannelBytesPerSample [maxASIOChannels];
|
||||
int outputChannelBytesPerSample [maxASIOChannels];
|
||||
bool inputChannelIsFloat [maxASIOChannels];
|
||||
bool outputChannelIsFloat [maxASIOChannels];
|
||||
bool inputChannelLittleEndian [maxASIOChannels];
|
||||
bool outputChannelLittleEndian [maxASIOChannels];
|
||||
|
||||
WaitableEvent event1;
|
||||
float* tempBuffer;
|
||||
int volatile bufferIndex, numActiveInputChans, numActiveOutputChans;
|
||||
|
||||
bool isOpen_, isStarted;
|
||||
bool isUsingThread, shouldUseThread;
|
||||
bool volatile isASIOOpen;
|
||||
bool volatile calledback;
|
||||
bool volatile littleEndian, postOutput, needToReset, isReSync, isThreadReady;
|
||||
bool volatile insideControlPanelModalLoop;
|
||||
bool volatile shouldUsePreferredSize;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
static void removeCurrentDriver()
|
||||
void removeCurrentDriver()
|
||||
{
|
||||
if (asioObject != 0)
|
||||
{
|
||||
|
|
@ -1006,8 +976,6 @@ private:
|
|||
modalWindow.addToDesktop (0);
|
||||
modalWindow.enterModalState();
|
||||
|
||||
isUsingThread = shouldUseThread;
|
||||
|
||||
// open the device and get its info..
|
||||
log (T("opening ASIO device: ") + getName());
|
||||
|
||||
|
|
@ -1019,8 +987,10 @@ private:
|
|||
sampleRates.clear();
|
||||
isASIOOpen = false;
|
||||
isOpen_ = false;
|
||||
numInputs = 0;
|
||||
numOutputs = 0;
|
||||
totalNumInputChans = 0;
|
||||
totalNumOutputChans = 0;
|
||||
numActiveInputChans = 0;
|
||||
numActiveOutputChans = 0;
|
||||
currentCallback = 0;
|
||||
|
||||
error = String::empty;
|
||||
|
|
@ -1032,17 +1002,17 @@ private:
|
|||
|
||||
if (loadDriver())
|
||||
{
|
||||
String driverName;
|
||||
|
||||
if ((error = initDriver()).isEmpty())
|
||||
{
|
||||
numInputs = 0;
|
||||
numOutputs = 0;
|
||||
numActiveInputChans = 0;
|
||||
numActiveOutputChans = 0;
|
||||
totalNumInputChans = 0;
|
||||
totalNumOutputChans = 0;
|
||||
|
||||
if (asioObject != 0
|
||||
&& (err = asioObject->getChannels (&numInputs, &numOutputs)) == 0)
|
||||
&& (err = asioObject->getChannels (&totalNumInputChans, &totalNumOutputChans)) == 0)
|
||||
{
|
||||
log (String ((int) numInputs) + T(" in, ") + String ((int) numOutputs) + T(" out"));
|
||||
log (String ((int) totalNumInputChans) + T(" in, ") + String ((int) totalNumOutputChans) + T(" out"));
|
||||
|
||||
if ((err = asioObject->getBufferSize (&minSize, &maxSize, &preferredSize, &granularity)) == 0)
|
||||
{
|
||||
|
|
@ -1112,7 +1082,7 @@ private:
|
|||
|
||||
ASIOBufferInfo* info = bufferInfos;
|
||||
int i, numChans = 0;
|
||||
for (i = 0; i < jmin (2, numInputs); ++i)
|
||||
for (i = 0; i < jmin (2, totalNumInputChans); ++i)
|
||||
{
|
||||
info->isInput = 1;
|
||||
info->channelNum = i;
|
||||
|
|
@ -1123,7 +1093,7 @@ private:
|
|||
|
||||
const int outputBufferIndex = numChans;
|
||||
|
||||
for (i = 0; i < jmin (2, numOutputs); ++i)
|
||||
for (i = 0; i < jmin (2, totalNumOutputChans); ++i)
|
||||
{
|
||||
info->isInput = 0;
|
||||
info->channelNum = i;
|
||||
|
|
@ -1132,10 +1102,31 @@ private:
|
|||
++numChans;
|
||||
}
|
||||
|
||||
callbacks.bufferSwitch = &bufferSwitchCallback;
|
||||
|
||||
callbacks.sampleRateDidChange = &sampleRateChangedCallback;
|
||||
callbacks.asioMessage = &asioMessagesCallback;
|
||||
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback;
|
||||
|
||||
if (currentASIODev[0] == this)
|
||||
{
|
||||
callbacks.bufferSwitch = &bufferSwitchCallback0;
|
||||
callbacks.asioMessage = &asioMessagesCallback0;
|
||||
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback0;
|
||||
}
|
||||
else if (currentASIODev[1] == this)
|
||||
{
|
||||
callbacks.bufferSwitch = &bufferSwitchCallback1;
|
||||
callbacks.asioMessage = &asioMessagesCallback1;
|
||||
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback1;
|
||||
}
|
||||
else if (currentASIODev[2] == this)
|
||||
{
|
||||
callbacks.bufferSwitch = &bufferSwitchCallback2;
|
||||
callbacks.asioMessage = &asioMessagesCallback2;
|
||||
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback2;
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse
|
||||
}
|
||||
|
||||
log (T("creating buffers (dummy): ") + String (numChans)
|
||||
+ T(", ") + String ((int) preferredSize));
|
||||
|
|
@ -1152,13 +1143,13 @@ private:
|
|||
long newInps = 0, newOuts = 0;
|
||||
asioObject->getChannels (&newInps, &newOuts);
|
||||
|
||||
if (numInputs != newInps || numOutputs != newOuts)
|
||||
if (totalNumInputChans != newInps || totalNumOutputChans != newOuts)
|
||||
{
|
||||
numInputs = newInps;
|
||||
numOutputs = newOuts;
|
||||
totalNumInputChans = newInps;
|
||||
totalNumOutputChans = newOuts;
|
||||
|
||||
log (String ((int) numInputs) + T(" in; ")
|
||||
+ String ((int) numOutputs) + T(" out"));
|
||||
log (String ((int) totalNumInputChans) + T(" in; ")
|
||||
+ String ((int) totalNumOutputChans) + T(" out"));
|
||||
}
|
||||
|
||||
updateSampleRates();
|
||||
|
|
@ -1166,7 +1157,7 @@ private:
|
|||
ASIOChannelInfo channelInfo;
|
||||
channelInfo.type = 0;
|
||||
|
||||
for (i = 0; i < numInputs; ++i)
|
||||
for (i = 0; i < totalNumInputChans; ++i)
|
||||
{
|
||||
zerostruct (channelInfo);
|
||||
channelInfo.channel = i;
|
||||
|
|
@ -1176,7 +1167,7 @@ private:
|
|||
inputChannelNames.add (String (channelInfo.name));
|
||||
}
|
||||
|
||||
for (i = 0; i < numOutputs; ++i)
|
||||
for (i = 0; i < totalNumOutputChans; ++i)
|
||||
{
|
||||
zerostruct (channelInfo);
|
||||
channelInfo.channel = i;
|
||||
|
|
@ -1262,18 +1253,7 @@ private:
|
|||
if (isStarted)
|
||||
{
|
||||
bufferIndex = index;
|
||||
|
||||
if (isUsingThread) // if not started, just use processBuffer() to clear the buffers directly
|
||||
{
|
||||
event1.signal();
|
||||
|
||||
if (postOutput && (! isThreadRunning()) && asioObject != 0)
|
||||
asioObject->outputReady();
|
||||
}
|
||||
else
|
||||
{
|
||||
processBuffer();
|
||||
}
|
||||
processBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1312,117 +1292,99 @@ private:
|
|||
|
||||
if (currentCallback != 0)
|
||||
{
|
||||
int n = 0;
|
||||
int i;
|
||||
for (i = 0; i < numInputs; ++i)
|
||||
for (i = 0; i < numActiveInputChans; ++i)
|
||||
{
|
||||
float* const dst = inBuffers[i];
|
||||
|
||||
if (dst != 0)
|
||||
jassert (dst != 0);
|
||||
|
||||
const char* const src = (const char*) (infos[i].buffers[bi]);
|
||||
|
||||
if (inputChannelIsFloat[i])
|
||||
{
|
||||
const char* const src = (const char*) (infos[n].buffers[bi]);
|
||||
memcpy (dst, src, samps * sizeof (float));
|
||||
}
|
||||
else
|
||||
{
|
||||
jassert (dst == tempBuffer + (samps * i));
|
||||
|
||||
if (inputChannelIsFloat[i])
|
||||
switch (inputChannelBitDepths[i])
|
||||
{
|
||||
memcpy (dst, src, samps * sizeof (float));
|
||||
case 16:
|
||||
convertInt16ToFloat (src, dst, inputChannelBytesPerSample[i],
|
||||
samps, inputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 24:
|
||||
convertInt24ToFloat (src, dst, inputChannelBytesPerSample[i],
|
||||
samps, inputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
convertInt32ToFloat (src, dst, inputChannelBytesPerSample[i],
|
||||
samps, inputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 64:
|
||||
jassertfalse
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
jassert (dst == tempBuffer + (samps * n));
|
||||
|
||||
switch (inputChannelBitDepths[i])
|
||||
{
|
||||
case 16:
|
||||
convertInt16ToFloat (src, dst, inputChannelBytesPerSample[i],
|
||||
samps, inputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 24:
|
||||
convertInt24ToFloat (src, dst, inputChannelBytesPerSample[i],
|
||||
samps, inputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
convertInt32ToFloat (src, dst, inputChannelBytesPerSample[i],
|
||||
samps, inputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 64:
|
||||
jassertfalse
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
}
|
||||
|
||||
currentCallback->audioDeviceIOCallback ((const float**) inBuffers,
|
||||
numInputs,
|
||||
numActiveInputChans,
|
||||
outBuffers,
|
||||
numOutputs,
|
||||
numActiveOutputChans,
|
||||
samps);
|
||||
|
||||
for (i = 0; i < numOutputs; ++i)
|
||||
for (i = 0; i < numActiveOutputChans; ++i)
|
||||
{
|
||||
float* const src = outBuffers[i];
|
||||
|
||||
if (src != 0)
|
||||
jassert (src != 0);
|
||||
|
||||
char* const dst = (char*) (infos [numActiveInputChans + i].buffers[bi]);
|
||||
|
||||
if (outputChannelIsFloat[i])
|
||||
{
|
||||
char* const dst = (char*) (infos[n].buffers[bi]);
|
||||
memcpy (dst, src, samps * sizeof (float));
|
||||
}
|
||||
else
|
||||
{
|
||||
jassert (src == tempBuffer + (samps * (numActiveInputChans + i)));
|
||||
|
||||
if (outputChannelIsFloat[i])
|
||||
switch (outputChannelBitDepths[i])
|
||||
{
|
||||
memcpy (dst, src, samps * sizeof (float));
|
||||
case 16:
|
||||
convertFloatToInt16 (src, dst, outputChannelBytesPerSample[i],
|
||||
samps, outputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 24:
|
||||
convertFloatToInt24 (src, dst, outputChannelBytesPerSample[i],
|
||||
samps, outputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
convertFloatToInt32 (src, dst, outputChannelBytesPerSample[i],
|
||||
samps, outputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 64:
|
||||
jassertfalse
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
jassert (src == tempBuffer + (samps * n));
|
||||
|
||||
switch (outputChannelBitDepths[i])
|
||||
{
|
||||
case 16:
|
||||
convertFloatToInt16 (src, dst, outputChannelBytesPerSample[i],
|
||||
samps, outputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 24:
|
||||
convertFloatToInt24 (src, dst, outputChannelBytesPerSample[i],
|
||||
samps, outputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
convertFloatToInt32 (src, dst, outputChannelBytesPerSample[i],
|
||||
samps, outputChannelLittleEndian[i]);
|
||||
break;
|
||||
|
||||
case 64:
|
||||
jassertfalse
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
++n;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < numInputs; ++i)
|
||||
if (inBuffers[i] != 0)
|
||||
++n;
|
||||
|
||||
for (i = 0; i < numOutputs; ++i)
|
||||
for (int i = 0; i < numActiveOutputChans; ++i)
|
||||
{
|
||||
if (outBuffers[i] != 0)
|
||||
{
|
||||
const int bytesPerBuffer = samps * (outputChannelBitDepths[i] >> 3);
|
||||
zeromem (infos[n].buffers[bi], bytesPerBuffer);
|
||||
++n;
|
||||
}
|
||||
const int bytesPerBuffer = samps * (outputChannelBitDepths[i] >> 3);
|
||||
zeromem (infos[numActiveInputChans + i].buffers[bi], bytesPerBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1432,21 +1394,65 @@ private:
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
static ASIOTime* bufferSwitchTimeInfoCallback (ASIOTime*, long index, long) throw()
|
||||
static ASIOTime* bufferSwitchTimeInfoCallback0 (ASIOTime*, long index, long) throw()
|
||||
{
|
||||
if (currentASIODev != 0)
|
||||
currentASIODev->callback (index);
|
||||
if (currentASIODev[0] != 0)
|
||||
currentASIODev[0]->callback (index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bufferSwitchCallback (long index, long) throw()
|
||||
static ASIOTime* bufferSwitchTimeInfoCallback1 (ASIOTime*, long index, long) throw()
|
||||
{
|
||||
if (currentASIODev != 0)
|
||||
currentASIODev->callback (index);
|
||||
if (currentASIODev[1] != 0)
|
||||
currentASIODev[1]->callback (index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long asioMessagesCallback (long selector, long value, void*, double*) throw()
|
||||
static ASIOTime* bufferSwitchTimeInfoCallback2 (ASIOTime*, long index, long) throw()
|
||||
{
|
||||
if (currentASIODev[2] != 0)
|
||||
currentASIODev[2]->callback (index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bufferSwitchCallback0 (long index, long) throw()
|
||||
{
|
||||
if (currentASIODev[0] != 0)
|
||||
currentASIODev[0]->callback (index);
|
||||
}
|
||||
|
||||
static void bufferSwitchCallback1 (long index, long) throw()
|
||||
{
|
||||
if (currentASIODev[1] != 0)
|
||||
currentASIODev[1]->callback (index);
|
||||
}
|
||||
|
||||
static void bufferSwitchCallback2 (long index, long) throw()
|
||||
{
|
||||
if (currentASIODev[2] != 0)
|
||||
currentASIODev[2]->callback (index);
|
||||
}
|
||||
|
||||
static long asioMessagesCallback0 (long selector, long value, void*, double*) throw()
|
||||
{
|
||||
return asioMessagesCallback (selector, value, 0);
|
||||
}
|
||||
|
||||
static long asioMessagesCallback1 (long selector, long value, void*, double*) throw()
|
||||
{
|
||||
return asioMessagesCallback (selector, value, 1);
|
||||
}
|
||||
|
||||
static long asioMessagesCallback2 (long selector, long value, void*, double*) throw()
|
||||
{
|
||||
return asioMessagesCallback (selector, value, 2);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static long asioMessagesCallback (long selector, long value, const int deviceIndex) throw()
|
||||
{
|
||||
switch (selector)
|
||||
{
|
||||
|
|
@ -1463,14 +1469,14 @@ private:
|
|||
break;
|
||||
|
||||
case kAsioResetRequest:
|
||||
if (currentASIODev != 0)
|
||||
currentASIODev->resetRequest();
|
||||
if (currentASIODev[deviceIndex] != 0)
|
||||
currentASIODev[deviceIndex]->resetRequest();
|
||||
|
||||
return 1;
|
||||
|
||||
case kAsioResyncRequest:
|
||||
if (currentASIODev != 0)
|
||||
currentASIODev->resyncRequest();
|
||||
if (currentASIODev[deviceIndex] != 0)
|
||||
currentASIODev[deviceIndex]->resyncRequest();
|
||||
|
||||
return 1;
|
||||
|
||||
|
|
@ -1827,11 +1833,22 @@ public:
|
|||
|
||||
if (index >= 0)
|
||||
{
|
||||
jassert (currentASIODev == 0); // unfortunately you can't have more than one ASIO device
|
||||
// open at the same time..
|
||||
int freeSlot = -1;
|
||||
|
||||
if (currentASIODev == 0)
|
||||
return new ASIOAudioIODevice (deviceName, *(classIds [index]));
|
||||
for (int i = 0; i < numElementsInArray (currentASIODev); ++i)
|
||||
{
|
||||
if (currentASIODev[i] == 0)
|
||||
{
|
||||
freeSlot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
jassert (freeSlot >= 0); // unfortunately you can only have a finite number
|
||||
// of ASIO devices open at the same time..
|
||||
|
||||
if (freeSlot >= 0)
|
||||
return new ASIOAudioIODevice (deviceName, *(classIds [index]), freeSlot);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1110,12 +1110,10 @@ public:
|
|||
int i, bits = 256;
|
||||
|
||||
for (i = inChans.size(); --i >= 0;)
|
||||
if (inChans[i] != 0)
|
||||
bits = jmin (bits, inChans[i]->bitDepth);
|
||||
bits = jmin (bits, inChans[i]->bitDepth);
|
||||
|
||||
for (i = outChans.size(); --i >= 0;)
|
||||
if (outChans[i] != 0)
|
||||
bits = jmin (bits, outChans[i]->bitDepth);
|
||||
bits = jmin (bits, outChans[i]->bitDepth);
|
||||
|
||||
if (bits > 32)
|
||||
bits = 16;
|
||||
|
|
@ -1250,18 +1248,10 @@ private:
|
|||
{
|
||||
int i;
|
||||
for (i = outChans.size(); --i >= 0;)
|
||||
{
|
||||
DSoundInternalOutChannel* const out = outChans.getUnchecked(i);
|
||||
if (out != 0)
|
||||
out->close();
|
||||
}
|
||||
outChans.getUnchecked(i)->close();
|
||||
|
||||
for (i = inChans.size(); --i >= 0;)
|
||||
{
|
||||
DSoundInternalInChannel* const in = inChans.getUnchecked(i);
|
||||
if (in != 0)
|
||||
in->close();
|
||||
}
|
||||
inChans.getUnchecked(i)->close();
|
||||
|
||||
if (threadShouldExit())
|
||||
return;
|
||||
|
|
@ -1273,30 +1263,20 @@ private:
|
|||
SetPriorityClass (GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
|
||||
|
||||
for (i = outChans.size(); --i >= 0;)
|
||||
{
|
||||
DSoundInternalOutChannel* const out = outChans.getUnchecked(i);
|
||||
if (out != 0)
|
||||
out->open();
|
||||
}
|
||||
outChans.getUnchecked(i)->open();
|
||||
|
||||
for (i = inChans.size(); --i >= 0;)
|
||||
{
|
||||
DSoundInternalInChannel* const in = inChans.getUnchecked(i);
|
||||
if (in != 0)
|
||||
in->open();
|
||||
}
|
||||
inChans.getUnchecked(i)->open();
|
||||
|
||||
if (! threadShouldExit())
|
||||
{
|
||||
sleep (5);
|
||||
|
||||
for (i = 0; i < numOutputBuffers; ++i)
|
||||
if (outChans[i] != 0)
|
||||
outChans[i]->synchronisePosition();
|
||||
for (i = 0; i < outChans.size(); ++i)
|
||||
outChans.getUnchecked(i)->synchronisePosition();
|
||||
|
||||
for (i = 0; i < numInputBuffers; ++i)
|
||||
if (inChans[i] != 0)
|
||||
inChans[i]->synchronisePosition();
|
||||
for (i = 0; i < inChans.size(); ++i)
|
||||
inChans.getUnchecked(i)->synchronisePosition();
|
||||
}
|
||||
|
||||
SetThreadPriority (GetCurrentThread(), oldThreadPri);
|
||||
|
|
@ -1323,24 +1303,14 @@ public:
|
|||
int i;
|
||||
for (i = inChans.size(); --i >= 0;)
|
||||
{
|
||||
DSoundInternalInChannel* const in = inChans.getUnchecked(i);
|
||||
|
||||
if (in != 0)
|
||||
{
|
||||
in->doneFlag = false;
|
||||
++numToDo;
|
||||
}
|
||||
inChans.getUnchecked(i)->doneFlag = false;
|
||||
++numToDo;
|
||||
}
|
||||
|
||||
for (i = outChans.size(); --i >= 0;)
|
||||
{
|
||||
DSoundInternalOutChannel* const out = outChans.getUnchecked(i);
|
||||
|
||||
if (out != 0)
|
||||
{
|
||||
out->doneFlag = false;
|
||||
++numToDo;
|
||||
}
|
||||
outChans.getUnchecked(i)->doneFlag = false;
|
||||
++numToDo;
|
||||
}
|
||||
|
||||
if (numToDo > 0)
|
||||
|
|
@ -1354,13 +1324,10 @@ public:
|
|||
{
|
||||
DSoundInternalInChannel* const in = inChans.getUnchecked(i);
|
||||
|
||||
if (in != 0 && !in->doneFlag)
|
||||
if ((! in->doneFlag) && in->service())
|
||||
{
|
||||
if (in->service())
|
||||
{
|
||||
in->doneFlag = true;
|
||||
--numToDo;
|
||||
}
|
||||
in->doneFlag = true;
|
||||
--numToDo;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1368,13 +1335,10 @@ public:
|
|||
{
|
||||
DSoundInternalOutChannel* const out = outChans.getUnchecked(i);
|
||||
|
||||
if (out != 0 && !out->doneFlag)
|
||||
if ((! out->doneFlag) && out->service())
|
||||
{
|
||||
if (out->service())
|
||||
{
|
||||
out->doneFlag = true;
|
||||
--numToDo;
|
||||
}
|
||||
out->doneFlag = true;
|
||||
--numToDo;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1649,71 +1613,52 @@ const String DSoundAudioIODevice::openDevice (const BitArray& inputChannels,
|
|||
DSoundAudioIODeviceType dlh;
|
||||
dlh.scanForDevices();
|
||||
|
||||
numInputBuffers = 2 * dlh.inputDeviceNames.size();
|
||||
enabledInputs = inputChannels;
|
||||
numInputBuffers = inputChannels.countNumberOfSetBits();
|
||||
inputBuffers = new float* [numInputBuffers + 2];
|
||||
zeromem (inputBuffers, sizeof (inputBuffers));
|
||||
int i, numIns = 0;
|
||||
|
||||
numOutputBuffers = 2 * dlh.outputDeviceNames.size();
|
||||
outputBuffers = new float* [numOutputBuffers + 2];
|
||||
|
||||
int i;
|
||||
for (i = 0; i < numInputBuffers + 2; ++i)
|
||||
for (i = 0; i < inputChannels.getHighestBit(); i += 2)
|
||||
{
|
||||
if (inputChannels[i] && i < numInputBuffers)
|
||||
{
|
||||
inputBuffers[i] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float));
|
||||
enabledInputs.setBit (i);
|
||||
}
|
||||
else
|
||||
{
|
||||
inputBuffers[i] = 0;
|
||||
}
|
||||
}
|
||||
float* left = 0;
|
||||
float* right = 0;
|
||||
|
||||
for (i = 0; i < numOutputBuffers + 2; ++i)
|
||||
{
|
||||
if (outputChannels[i] && i < numOutputBuffers)
|
||||
{
|
||||
outputBuffers[i] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float));
|
||||
enabledOutputs.setBit (i);
|
||||
}
|
||||
else
|
||||
{
|
||||
outputBuffers[i] = 0;
|
||||
}
|
||||
}
|
||||
if (inputChannels[i])
|
||||
left = inputBuffers[numIns++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float));
|
||||
|
||||
for (i = 0; i < numInputBuffers; ++i)
|
||||
{
|
||||
if (inputChannels[i] || inputChannels[i + 1])
|
||||
{
|
||||
if (inputChannels[i + 1])
|
||||
right = inputBuffers[numIns++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float));
|
||||
|
||||
if (left != 0 || right != 0)
|
||||
inChans.add (new DSoundInternalInChannel (dlh.inputDeviceNames [i / 2],
|
||||
dlh.inputGuids [i / 2],
|
||||
(int) sampleRate, bufferSizeSamples,
|
||||
inputBuffers[i], inputBuffers[i + 1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
inChans.add (0);
|
||||
}
|
||||
|
||||
++i;
|
||||
left, right));
|
||||
}
|
||||
|
||||
for (i = 0; i < numOutputBuffers; ++i)
|
||||
enabledOutputs = outputChannels;
|
||||
numOutputBuffers = outputChannels.countNumberOfSetBits();
|
||||
outputBuffers = new float* [numOutputBuffers + 2];
|
||||
zeromem (outputBuffers, sizeof (outputBuffers));
|
||||
int numOuts = 0;
|
||||
|
||||
for (i = 0; i < outputChannels.getHighestBit(); i += 2)
|
||||
{
|
||||
if (outputChannels[i] || outputChannels[i + 1])
|
||||
{
|
||||
float* left = 0;
|
||||
float* right = 0;
|
||||
|
||||
if (inputChannels[i])
|
||||
left = outputBuffers[numOuts++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float));
|
||||
|
||||
if (inputChannels[i + 1])
|
||||
right = outputBuffers[numOuts++] = (float*) juce_calloc ((bufferSizeSamples + 16) * sizeof (float));
|
||||
|
||||
if (left != 0 || right != 0)
|
||||
outChans.add (new DSoundInternalOutChannel (dlh.outputDeviceNames[i / 2],
|
||||
dlh.outputGuids [i / 2],
|
||||
(int) sampleRate, bufferSizeSamples,
|
||||
outputBuffers[i], outputBuffers[i + 1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
outChans.add (0);
|
||||
}
|
||||
|
||||
++i;
|
||||
left, right));
|
||||
}
|
||||
|
||||
String error;
|
||||
|
|
@ -1724,35 +1669,29 @@ const String DSoundAudioIODevice::openDevice (const BitArray& inputChannels,
|
|||
SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
|
||||
SetPriorityClass (GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
|
||||
|
||||
for (i = 0; i < numOutputBuffers; ++i)
|
||||
for (i = 0; i < outChans.size(); ++i)
|
||||
{
|
||||
if (outChans[i] != 0)
|
||||
{
|
||||
error = outChans[i]->open();
|
||||
error = outChans[i]->open();
|
||||
|
||||
if (error.isNotEmpty())
|
||||
{
|
||||
error = T("Error opening ") + dlh.outputDeviceNames[i]
|
||||
+ T(": \"") + error + T("\"");
|
||||
break;
|
||||
}
|
||||
if (error.isNotEmpty())
|
||||
{
|
||||
error = T("Error opening ") + dlh.outputDeviceNames[i]
|
||||
+ T(": \"") + error + T("\"");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error.isEmpty())
|
||||
{
|
||||
for (i = 0; i < numInputBuffers; ++i)
|
||||
for (i = 0; i < inChans.size(); ++i)
|
||||
{
|
||||
if (inChans[i] != 0)
|
||||
{
|
||||
error = inChans[i]->open();
|
||||
error = inChans[i]->open();
|
||||
|
||||
if (error.isNotEmpty())
|
||||
{
|
||||
error = T("Error opening ") + dlh.inputDeviceNames[i]
|
||||
+ T(": \"") + error + T("\"");
|
||||
break;
|
||||
}
|
||||
if (error.isNotEmpty())
|
||||
{
|
||||
error = T("Error opening ") + dlh.inputDeviceNames[i]
|
||||
+ T(": \"") + error + T("\"");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1761,13 +1700,11 @@ const String DSoundAudioIODevice::openDevice (const BitArray& inputChannels,
|
|||
{
|
||||
totalSamplesOut = 0;
|
||||
|
||||
for (i = 0; i < numOutputBuffers; ++i)
|
||||
if (outChans[i] != 0)
|
||||
outChans[i]->synchronisePosition();
|
||||
for (i = 0; i < outChans.size(); ++i)
|
||||
outChans.getUnchecked(i)->synchronisePosition();
|
||||
|
||||
for (i = 0; i < numInputBuffers; ++i)
|
||||
if (inChans[i] != 0)
|
||||
inChans[i]->synchronisePosition();
|
||||
for (i = 0; i < inChans.size(); ++i)
|
||||
inChans.getUnchecked(i)->synchronisePosition();
|
||||
|
||||
startThread (9);
|
||||
sleep (10);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ Changelist for version 1.46
|
|||
- added an option to splash screens to close themselves when the mouse is clicked
|
||||
- change to ProgressBar to allow custom text and bars that are just spinning without a known progress position. This also meant a change to the params for LookAndFeel::drawProgressBar
|
||||
- ditched win98 non-unicode support (presumably nobody will miss that!)
|
||||
- change to the way that channel data is passed to an AudioIODeviceCallback. Previously, some of the channels could be null, but now is uses a packed array of all the active channels
|
||||
|
||||
==============================================================================
|
||||
Changelist for version 1.45
|
||||
|
|
|
|||
|
|
@ -194,7 +194,8 @@ your "External Frameworks and Libraries" list, or to add switch to the linker's
|
|||
or "-ljucedebug".</li>
|
||||
<li>You'll also need to add some of the following OSX frameworks to your "External Frameworks and Libraries" list,
|
||||
depending on what features your application uses:
|
||||
<pre>Carbon.framework
|
||||
<pre>Cocoa.framework
|
||||
Carbon.framework
|
||||
IOKit.framework
|
||||
CoreAudio.framework
|
||||
CoreMIDI.framework
|
||||
|
|
|
|||
|
|
@ -68,23 +68,22 @@ public:
|
|||
|
||||
@param inputChannelData a set of arrays containing the audio data for each
|
||||
incoming channel - this data is valid until the function
|
||||
returns. Some members of the array may be null pointers, if
|
||||
that channel wasn't enabled when the audio device was
|
||||
opened (see AudioIODevice::open())
|
||||
@param totalNumInputChannels the total number of pointers to channel data in
|
||||
the inputChannelData array. Note that not all of these
|
||||
channels may be active, so some may be null pointers
|
||||
returns. There will be one channel of data for each input
|
||||
channel that was enabled when the audio device was opened
|
||||
(see AudioIODevice::open())
|
||||
@param numInputChannels the number of pointers to channel data in the
|
||||
inputChannelData array.
|
||||
@param outputChannelData a set of arrays which need to be filled with the data
|
||||
that should be sent to each outgoing channel of the device.
|
||||
As for the input array, some of these pointers may be null, if
|
||||
those channels weren't enabled when the audio device was
|
||||
opened. The contents of the array are undefined, so the
|
||||
There will be one channel of data for each output channel
|
||||
that was enabled when the audio device was opened (see
|
||||
AudioIODevice::open())
|
||||
The initial contents of the array is undefined, so the
|
||||
callback function must fill all the channels with zeros if
|
||||
it wants to output silence - not doing this could cause quite
|
||||
its output is silence. Failing to do this could cause quite
|
||||
an unpleasant noise!
|
||||
@param totalNumOutputChannels the total number of pointers to channel data in
|
||||
the outputChannelData array. Note that not all of these
|
||||
channels may be active, so some may be null pointers
|
||||
@param numOutputChannels the number of pointers to channel data in the
|
||||
outputChannelData array.
|
||||
@param numSamples the number of samples in each channel of the input and
|
||||
output arrays. The number of samples will depend on the
|
||||
audio device's buffer size and will usually remain constant,
|
||||
|
|
@ -93,9 +92,9 @@ public:
|
|||
callback to the next.
|
||||
*/
|
||||
virtual void audioDeviceIOCallback (const float** inputChannelData,
|
||||
int totalNumInputChannels,
|
||||
int numInputChannels,
|
||||
float** outputChannelData,
|
||||
int totalNumOutputChannels,
|
||||
int numOutputChannels,
|
||||
int numSamples) = 0;
|
||||
|
||||
/** Called to indicate that the device is about to start calling back.
|
||||
|
|
@ -122,7 +121,7 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
/**
|
||||
Base class for an audio device with synchoronised input and output channels.
|
||||
Base class for an audio device with synchronised input and output channels.
|
||||
|
||||
Subclasses of this are used to implement different protocols such as DirectSound,
|
||||
ASIO, CoreAudio, etc.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue