- Library code update
- project update (added Eigen) git-svn-id: http://moon:8086/svn/software/trunk/projects/mpsk_rx_gui@94 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -80,7 +80,7 @@ public:
|
||||
|
||||
Array<double> getAvailableSampleRates() override
|
||||
{
|
||||
static const double rates[] = { 8000.0, 16000.0, 32000.0, 44100.0, 48000.0 };
|
||||
static const double rates[] = { 8000.0, 16000.0, 32000.0, 44100.0, 48000.0 };
|
||||
return Array<double> (rates, numElementsInArray (rates));
|
||||
}
|
||||
|
||||
@@ -165,6 +165,33 @@ public:
|
||||
oldCallback->audioDeviceStopped();
|
||||
}
|
||||
|
||||
bool setAudioPreprocessingEnabled (bool enable) override
|
||||
{
|
||||
return recorder != nullptr && recorder->setAudioPreprocessingEnabled (enable);
|
||||
}
|
||||
|
||||
private:
|
||||
//==================================================================================================
|
||||
CriticalSection callbackLock;
|
||||
AudioIODeviceCallback* callback;
|
||||
int actualBufferSize, sampleRate;
|
||||
int inputLatency, outputLatency;
|
||||
bool deviceOpen;
|
||||
String lastError;
|
||||
BigInteger activeOutputChans, activeInputChans;
|
||||
int numInputChannels, numOutputChannels;
|
||||
AudioSampleBuffer inputBuffer, outputBuffer;
|
||||
struct Player;
|
||||
struct Recorder;
|
||||
|
||||
AudioIODeviceCallback* setCallback (AudioIODeviceCallback* const newCallback)
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
AudioIODeviceCallback* const oldCallback = callback;
|
||||
callback = newCallback;
|
||||
return oldCallback;
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
if (recorder != nullptr) recorder->start();
|
||||
@@ -190,28 +217,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
//==================================================================================================
|
||||
CriticalSection callbackLock;
|
||||
AudioIODeviceCallback* callback;
|
||||
int actualBufferSize, sampleRate;
|
||||
int inputLatency, outputLatency;
|
||||
bool deviceOpen;
|
||||
String lastError;
|
||||
BigInteger activeOutputChans, activeInputChans;
|
||||
int numInputChannels, numOutputChannels;
|
||||
AudioSampleBuffer inputBuffer, outputBuffer;
|
||||
struct Player;
|
||||
struct Recorder;
|
||||
|
||||
AudioIODeviceCallback* setCallback (AudioIODeviceCallback* const newCallback)
|
||||
{
|
||||
const ScopedLock sl (callbackLock);
|
||||
AudioIODeviceCallback* const oldCallback = callback;
|
||||
callback = newCallback;
|
||||
return oldCallback;
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
struct Engine
|
||||
{
|
||||
@@ -230,6 +235,7 @@ private:
|
||||
SL_IID_ANDROIDSIMPLEBUFFERQUEUE = (SLInterfaceID*) library.getFunction ("SL_IID_ANDROIDSIMPLEBUFFERQUEUE");
|
||||
SL_IID_PLAY = (SLInterfaceID*) library.getFunction ("SL_IID_PLAY");
|
||||
SL_IID_RECORD = (SLInterfaceID*) library.getFunction ("SL_IID_RECORD");
|
||||
SL_IID_ANDROIDCONFIGURATION = (SLInterfaceID*) library.getFunction ("SL_IID_ANDROIDCONFIGURATION");
|
||||
|
||||
check ((*engineObject)->Realize (engineObject, SL_BOOLEAN_FALSE));
|
||||
check ((*engineObject)->GetInterface (engineObject, *SL_IID_ENGINE, &engineInterface));
|
||||
@@ -271,6 +277,7 @@ private:
|
||||
SLInterfaceID* SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
|
||||
SLInterfaceID* SL_IID_PLAY;
|
||||
SLInterfaceID* SL_IID_RECORD;
|
||||
SLInterfaceID* SL_IID_ANDROIDCONFIGURATION;
|
||||
|
||||
private:
|
||||
DynamicLibrary library;
|
||||
@@ -334,8 +341,8 @@ private:
|
||||
SLDataFormat_PCM pcmFormat =
|
||||
{
|
||||
SL_DATAFORMAT_PCM,
|
||||
numChannels,
|
||||
sampleRate * 1000, // (sample rate units are millihertz)
|
||||
(SLuint32) numChannels,
|
||||
(SLuint32) (sampleRate * 1000), // (sample rate units are millihertz)
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
|
||||
@@ -434,7 +441,8 @@ private:
|
||||
struct Recorder
|
||||
{
|
||||
Recorder (int numChannels, int sampleRate, Engine& engine)
|
||||
: recorderObject (nullptr), recorderRecord (nullptr), recorderBufferQueue (nullptr),
|
||||
: recorderObject (nullptr), recorderRecord (nullptr),
|
||||
recorderBufferQueue (nullptr), configObject (nullptr),
|
||||
bufferList (numChannels)
|
||||
{
|
||||
jassert (numChannels == 1); // STEREO doesn't always work!!
|
||||
@@ -442,8 +450,8 @@ private:
|
||||
SLDataFormat_PCM pcmFormat =
|
||||
{
|
||||
SL_DATAFORMAT_PCM,
|
||||
numChannels,
|
||||
sampleRate * 1000, // (sample rate units are millihertz)
|
||||
(SLuint32) numChannels,
|
||||
(SLuint32) (sampleRate * 1000), // (sample rate units are millihertz)
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
SL_PCMSAMPLEFORMAT_FIXED_16,
|
||||
(numChannels == 1) ? SL_SPEAKER_FRONT_CENTER : (SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT),
|
||||
@@ -466,6 +474,7 @@ private:
|
||||
{
|
||||
check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_RECORD, &recorderRecord));
|
||||
check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_ANDROIDSIMPLEBUFFERQUEUE, &recorderBufferQueue));
|
||||
check ((*recorderObject)->GetInterface (recorderObject, *engine.SL_IID_ANDROIDCONFIGURATION, &configObject));
|
||||
check ((*recorderBufferQueue)->RegisterCallback (recorderBufferQueue, staticCallback, this));
|
||||
check ((*recorderRecord)->SetRecordState (recorderRecord, SL_RECORDSTATE_STOPPED));
|
||||
|
||||
@@ -532,10 +541,20 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
bool setAudioPreprocessingEnabled (bool enable)
|
||||
{
|
||||
SLuint32 mode = enable ? SL_ANDROID_RECORDING_PRESET_GENERIC
|
||||
: SL_ANDROID_RECORDING_PRESET_VOICE_RECOGNITION;
|
||||
|
||||
return configObject != nullptr
|
||||
&& check ((*configObject)->SetConfiguration (configObject, SL_ANDROID_KEY_RECORDING_PRESET, &mode, sizeof (mode)));
|
||||
}
|
||||
|
||||
private:
|
||||
SLObjectItf recorderObject;
|
||||
SLRecordItf recorderRecord;
|
||||
SLAndroidSimpleBufferQueueItf recorderBufferQueue;
|
||||
SLAndroidConfigurationItf configObject;
|
||||
|
||||
BufferList bufferList;
|
||||
|
||||
|
||||
@@ -67,7 +67,12 @@ public:
|
||||
return s;
|
||||
}
|
||||
|
||||
Array<double> getAvailableSampleRates() override { return sampleRates; }
|
||||
Array<double> getAvailableSampleRates() override
|
||||
{
|
||||
// can't find a good way to actually ask the device for which of these it supports..
|
||||
static const double rates[] = { 8000.0, 16000.0, 22050.0, 32000.0, 44100.0, 48000.0 };
|
||||
return Array<double> (rates, numElementsInArray (rates));
|
||||
}
|
||||
|
||||
Array<int> getAvailableBufferSizes() override
|
||||
{
|
||||
@@ -79,7 +84,7 @@ public:
|
||||
return r;
|
||||
}
|
||||
|
||||
int getDefaultBufferSize() override { return 1024; }
|
||||
int getDefaultBufferSize() override { return 1024; }
|
||||
|
||||
String open (const BigInteger& inputChannelsWanted,
|
||||
const BigInteger& outputChannelsWanted,
|
||||
@@ -117,10 +122,9 @@ public:
|
||||
AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, routingChangedStatic, this);
|
||||
|
||||
fixAudioRouteIfSetToReceiver();
|
||||
updateDeviceInfo();
|
||||
|
||||
setSessionFloat64Property (kAudioSessionProperty_PreferredHardwareSampleRate, targetSampleRate);
|
||||
updateSampleRates();
|
||||
updateDeviceInfo();
|
||||
|
||||
setSessionFloat32Property (kAudioSessionProperty_PreferredHardwareIOBufferDuration, preferredBufferSize / sampleRate);
|
||||
updateCurrentBufferSize();
|
||||
@@ -162,8 +166,15 @@ public:
|
||||
BigInteger getActiveOutputChannels() const override { return activeOutputChans; }
|
||||
BigInteger getActiveInputChannels() const override { return activeInputChans; }
|
||||
|
||||
int getOutputLatencyInSamples() override { return 0; } //xxx
|
||||
int getInputLatencyInSamples() override { return 0; } //xxx
|
||||
int getOutputLatencyInSamples() override { return getLatency (kAudioSessionProperty_CurrentHardwareOutputLatency); }
|
||||
int getInputLatencyInSamples() override { return getLatency (kAudioSessionProperty_CurrentHardwareInputLatency); }
|
||||
|
||||
int getLatency (AudioSessionPropertyID propID)
|
||||
{
|
||||
Float32 latency = 0;
|
||||
getSessionProperty (propID, latency);
|
||||
return roundToInt (latency * getCurrentSampleRate());
|
||||
}
|
||||
|
||||
void start (AudioIODeviceCallback* newCallback) override
|
||||
{
|
||||
@@ -197,11 +208,16 @@ public:
|
||||
bool isPlaying() override { return isRunning && callback != nullptr; }
|
||||
String getLastError() override { return lastError; }
|
||||
|
||||
bool setAudioPreprocessingEnabled (bool enable) override
|
||||
{
|
||||
return setSessionUInt32Property (kAudioSessionProperty_Mode, enable ? kAudioSessionMode_Default
|
||||
: kAudioSessionMode_Measurement);
|
||||
}
|
||||
|
||||
private:
|
||||
//==================================================================================================
|
||||
CriticalSection callbackLock;
|
||||
Float64 sampleRate;
|
||||
Array<Float64> sampleRates;
|
||||
int numInputChannels, numOutputChannels;
|
||||
int preferredBufferSize, actualBufferSize;
|
||||
bool isRunning;
|
||||
@@ -322,38 +338,6 @@ private:
|
||||
getSessionProperty (kAudioSessionProperty_AudioInputAvailable, audioInputIsAvailable);
|
||||
}
|
||||
|
||||
void updateSampleRates()
|
||||
{
|
||||
getSessionProperty (kAudioSessionProperty_CurrentHardwareSampleRate, sampleRate);
|
||||
|
||||
sampleRates.clear();
|
||||
sampleRates.add (sampleRate);
|
||||
|
||||
const int commonSampleRates[] = { 8000, 16000, 22050, 32000, 44100, 48000 };
|
||||
|
||||
for (int i = 0; i < numElementsInArray (commonSampleRates); ++i)
|
||||
{
|
||||
Float64 rate = (Float64) commonSampleRates[i];
|
||||
|
||||
if (rate != sampleRate)
|
||||
{
|
||||
setSessionFloat64Property (kAudioSessionProperty_PreferredHardwareSampleRate, rate);
|
||||
|
||||
Float64 actualSampleRate = 0.0;
|
||||
getSessionProperty (kAudioSessionProperty_CurrentHardwareSampleRate, actualSampleRate);
|
||||
|
||||
if (actualSampleRate == rate)
|
||||
sampleRates.add (actualSampleRate);
|
||||
}
|
||||
}
|
||||
|
||||
DefaultElementComparator<Float64> comparator;
|
||||
sampleRates.sort (comparator);
|
||||
|
||||
setSessionFloat64Property (kAudioSessionProperty_PreferredHardwareSampleRate, sampleRate);
|
||||
getSessionProperty (kAudioSessionProperty_CurrentHardwareSampleRate, sampleRate);
|
||||
}
|
||||
|
||||
void updateCurrentBufferSize()
|
||||
{
|
||||
Float32 bufferDuration = sampleRate > 0 ? (Float32) (preferredBufferSize / sampleRate) : 0.0f;
|
||||
@@ -455,12 +439,12 @@ private:
|
||||
static OSStatus processStatic (void* client, AudioUnitRenderActionFlags* flags, const AudioTimeStamp* time,
|
||||
UInt32 /*busNumber*/, UInt32 numFrames, AudioBufferList* data)
|
||||
{
|
||||
return static_cast <iOSAudioIODevice*> (client)->process (flags, time, numFrames, data);
|
||||
return static_cast<iOSAudioIODevice*> (client)->process (flags, time, numFrames, data);
|
||||
}
|
||||
|
||||
static void routingChangedStatic (void* client, AudioSessionPropertyID, UInt32 /*inDataSize*/, const void* propertyValue)
|
||||
{
|
||||
static_cast <iOSAudioIODevice*> (client)->routingChanged (propertyValue);
|
||||
static_cast<iOSAudioIODevice*> (client)->routingChanged (propertyValue);
|
||||
}
|
||||
|
||||
//==================================================================================================
|
||||
@@ -552,9 +536,9 @@ private:
|
||||
return AudioSessionGetProperty (propID, &valueSize, &result);
|
||||
}
|
||||
|
||||
static void setSessionUInt32Property (AudioSessionPropertyID propID, UInt32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); }
|
||||
static void setSessionFloat32Property (AudioSessionPropertyID propID, Float32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); }
|
||||
static void setSessionFloat64Property (AudioSessionPropertyID propID, Float64 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); }
|
||||
static bool setSessionUInt32Property (AudioSessionPropertyID propID, UInt32 v) noexcept { return AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; }
|
||||
static bool setSessionFloat32Property (AudioSessionPropertyID propID, Float32 v) noexcept { return AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; }
|
||||
static bool setSessionFloat64Property (AudioSessionPropertyID propID, Float64 v) noexcept { return AudioSessionSetProperty (propID, sizeof (v), &v) == kAudioSessionNoError; }
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice)
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace
|
||||
return err;
|
||||
}
|
||||
#else
|
||||
#define JUCE_ALSA_LOG(x)
|
||||
#define JUCE_ALSA_LOG(x) {}
|
||||
#define JUCE_CHECKED_RESULT(x) (x)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -144,6 +144,7 @@ public:
|
||||
: owner (d),
|
||||
inputLatency (0),
|
||||
outputLatency (0),
|
||||
bitDepth (32),
|
||||
callback (nullptr),
|
||||
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
|
||||
audioProcID (0),
|
||||
@@ -232,7 +233,7 @@ public:
|
||||
size = sizeof (nameNSString);
|
||||
|
||||
pa.mSelector = kAudioObjectPropertyElementName;
|
||||
pa.mElement = chanNum + 1;
|
||||
pa.mElement = (AudioObjectPropertyElement) chanNum + 1;
|
||||
|
||||
if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &nameNSString) == noErr)
|
||||
{
|
||||
@@ -352,6 +353,22 @@ public:
|
||||
return (int) lat;
|
||||
}
|
||||
|
||||
int getBitDepthFromDevice (AudioObjectPropertyScope scope) const
|
||||
{
|
||||
AudioObjectPropertyAddress pa;
|
||||
pa.mElement = kAudioObjectPropertyElementMaster;
|
||||
pa.mSelector = kAudioStreamPropertyPhysicalFormat;
|
||||
pa.mScope = scope;
|
||||
|
||||
AudioStreamBasicDescription asbd;
|
||||
UInt32 size = sizeof (asbd);
|
||||
|
||||
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &asbd)))
|
||||
return (int) asbd.mBitsPerChannel;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void updateDetailsFromDevice()
|
||||
{
|
||||
stopTimer();
|
||||
@@ -377,7 +394,7 @@ public:
|
||||
if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &sr)))
|
||||
sampleRate = sr;
|
||||
|
||||
UInt32 framesPerBuf = bufferSize;
|
||||
UInt32 framesPerBuf = (UInt32) bufferSize;
|
||||
size = sizeof (framesPerBuf);
|
||||
pa.mSelector = kAudioDevicePropertyBufferFrameSize;
|
||||
AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &framesPerBuf);
|
||||
@@ -392,6 +409,13 @@ public:
|
||||
StringArray newInNames (getChannelInfo (true, newInChans));
|
||||
StringArray newOutNames (getChannelInfo (false, newOutChans));
|
||||
|
||||
const int inputBitDepth = getBitDepthFromDevice (kAudioDevicePropertyScopeInput);
|
||||
const int outputBitDepth = getBitDepthFromDevice (kAudioDevicePropertyScopeOutput);
|
||||
|
||||
bitDepth = jmax (inputBitDepth, outputBitDepth);
|
||||
if (bitDepth <= 0)
|
||||
bitDepth = 32;
|
||||
|
||||
// after getting the new values, lock + apply them
|
||||
const ScopedLock sl (callbackLock);
|
||||
|
||||
@@ -728,6 +752,7 @@ public:
|
||||
//==============================================================================
|
||||
CoreAudioIODevice& owner;
|
||||
int inputLatency, outputLatency;
|
||||
int bitDepth;
|
||||
BigInteger activeInputChans, activeOutputChans;
|
||||
StringArray inChanNames, outChanNames;
|
||||
Array<double> sampleRates;
|
||||
@@ -886,7 +911,7 @@ public:
|
||||
Array<int> getAvailableBufferSizes() override { return internal->bufferSizes; }
|
||||
|
||||
double getCurrentSampleRate() override { return internal->getSampleRate(); }
|
||||
int getCurrentBitDepth() override { return 32; } // no way to find out, so just assume it's high..
|
||||
int getCurrentBitDepth() override { return internal->bitDepth; }
|
||||
int getCurrentBufferSizeSamples() override { return internal->getBufferSize(); }
|
||||
|
||||
int getDefaultBufferSize() override
|
||||
@@ -1387,7 +1412,7 @@ private:
|
||||
d.done = (d.numInputChans == 0);
|
||||
}
|
||||
|
||||
for (int tries = 3;;)
|
||||
for (int tries = 5;;)
|
||||
{
|
||||
bool anyRemaining = false;
|
||||
|
||||
@@ -1434,7 +1459,7 @@ private:
|
||||
d.done = (d.numOutputChans == 0);
|
||||
}
|
||||
|
||||
for (int tries = 3;;)
|
||||
for (int tries = 5;;)
|
||||
{
|
||||
bool anyRemaining = false;
|
||||
|
||||
|
||||
@@ -365,7 +365,7 @@ public:
|
||||
void updateSampleRates()
|
||||
{
|
||||
// find a list of sample rates..
|
||||
const int possibleSampleRates[] = { 44100, 48000, 88200, 96000, 176400, 192000 };
|
||||
const int possibleSampleRates[] = { 44100, 48000, 88200, 96000, 176400, 192000, 352800, 384000 };
|
||||
Array<double> newRates;
|
||||
|
||||
if (asioObject != nullptr)
|
||||
|
||||
@@ -33,8 +33,8 @@ namespace WasapiClasses
|
||||
void logFailure (HRESULT hr)
|
||||
{
|
||||
(void) hr;
|
||||
jassert (hr != 0x800401f0); // If you hit this, it means you're trying to call from
|
||||
// a thread which hasn't been initialised with CoInitialize().
|
||||
jassert (hr != (HRESULT) 0x800401f0); // If you hit this, it means you're trying to call from
|
||||
// a thread which hasn't been initialised with CoInitialize().
|
||||
|
||||
#if JUCE_WASAPI_LOGGING
|
||||
if (FAILED (hr))
|
||||
|
||||
Reference in New Issue
Block a user