Browse Source

Fixed buffer size and sample rate changes in iOS background audio

tags/2021-05-28
tpoole 8 years ago
parent
commit
4b69d0fb44
3 changed files with 61 additions and 12 deletions
  1. +2
    -0
      examples/Demo/Builds/iOS/Info-App.plist
  2. +2
    -1
      examples/Demo/JuceDemo.jucer
  3. +57
    -11
      modules/juce_audio_devices/native/juce_ios_Audio.cpp

+ 2
- 0
examples/Demo/Builds/iOS/Info-App.plist View File

@@ -10,6 +10,8 @@
</dict>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone input.</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CFBundleExecutable</key>


+ 2
- 1
examples/Demo/JuceDemo.jucer View File

@@ -35,7 +35,8 @@
</XCODE_MAC>
<XCODE_IPHONE targetFolder="Builds/iOS" vstFolder="~/SDKs/vstsdk2.4" rtasFolder="~/SDKs/PT_80_SDK"
objCExtraSuffix="Lpywnl" bigIcon="BvyE0d" iosScreenOrientation="portraitlandscape"
customPList="&lt;plist&gt;&#10;&lt;dict&gt;&#10;&#9;&lt;key&gt;NSAppTransportSecurity&lt;/key&gt;&#10;&#9;&lt;dict&gt;&#10;&#9;&#9;&lt;key&gt;NSAllowsArbitraryLoads&lt;/key&gt;&#10;&#9;&#9;&lt;true/&gt;&#10;&#9;&lt;/dict&gt;&#10;&lt;/dict&gt;&#10;&lt;/plist&gt;">
customPList="&lt;plist&gt;&#10;&lt;dict&gt;&#10;&#9;&lt;key&gt;NSAppTransportSecurity&lt;/key&gt;&#10;&#9;&lt;dict&gt;&#10;&#9;&#9;&lt;key&gt;NSAllowsArbitraryLoads&lt;/key&gt;&#10;&#9;&#9;&lt;true/&gt;&#10;&#9;&lt;/dict&gt;&#10;&lt;/dict&gt;&#10;&lt;/plist&gt;"
microphonePermissionNeeded="1">
<CONFIGURATIONS>
<CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="JuceDemo"
osxSDK="default" osxCompatibility="default" osxArchitecture="default"


+ 57
- 11
modules/juce_audio_devices/native/juce_ios_Audio.cpp View File

@@ -92,7 +92,7 @@ bool getNotificationValueForKey (NSNotification* notification, NSString* key, NS
- (id) init: (juce::AudioSessionHolder*) holder;
- (void) dealloc;
- (void) audioSessionDidChangeInterruptionType: (NSNotification*) notification;
- (void) audioSessionChangedInterruptionType: (NSNotification*) notification;
- (void) handleMediaServicesReset;
- (void) handleMediaServicesLost;
- (void) handleRouteChange: (NSNotification*) notification;
@@ -112,7 +112,7 @@ bool getNotificationValueForKey (NSNotification* notification, NSString* key, NS
auto centre = [NSNotificationCenter defaultCenter];
[centre addObserver: self
selector: @selector (audioSessionDidChangeInterruptionType:)
selector: @selector (audioSessionChangedInterruptionType:)
name: AVAudioSessionInterruptionNotification
object: session];
@@ -145,7 +145,7 @@ bool getNotificationValueForKey (NSNotification* notification, NSString* key, NS
[super dealloc];
}
- (void) audioSessionDidChangeInterruptionType: (NSNotification*) notification
- (void) audioSessionChangedInterruptionType: (NSNotification*) notification
{
NSUInteger value;
@@ -263,6 +263,11 @@ public:
// depending on whether the headphones are plugged in or not!
setAudioSessionActive (true);
AudioUnitRemovePropertyListenerWithUserData (audioUnit,
kAudioUnitProperty_StreamFormat,
handleStreamFormatChangeCallback,
this);
const double lowestRate = trySampleRate (4000);
const double highestRate = trySampleRate (192000);
@@ -274,7 +279,12 @@ public:
rate = jmax (rate, supportedRate);
}
trySampleRate (sampleRate);
trySampleRate (getCurrentSampleRate());
AudioUnitAddPropertyListener (audioUnit,
kAudioUnitProperty_StreamFormat,
handleStreamFormatChangeCallback,
this);
for (auto r : rates)
{
@@ -289,7 +299,7 @@ public:
{
Array<int> r;
for (int i = 6; i < 12; ++i)
for (int i = 6; i < 13; ++i)
r.add (1 << i);
return r;
@@ -487,7 +497,10 @@ public:
}
if (callback != nullptr)
{
callback->audioDeviceStopped();
callback->audioDeviceAboutToStart (this);
}
}
}
@@ -618,7 +631,8 @@ private:
actualBufferSize = roundToInt (sampleRate * session.IOBufferDuration);
JUCE_IOS_AUDIO_LOG ("AVAudioSession: sampleRate: " << sampleRate
<< "Hz, audioInputAvailable: " << (int) audioInputIsAvailable);
<< " Hz, audioInputAvailable: " << (int) audioInputIsAvailable
<< ", buffer size: " << actualBufferSize);
}
void updateCurrentBufferSize()
@@ -703,18 +717,17 @@ private:
AudioUnitInitialize (audioUnit);
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_MaximumFramesPerSlice,
kAudioUnitScope_Global, 0, &actualBufferSize, sizeof (actualBufferSize));
updateCurrentBufferSize();
if (AudioUnitGetProperty (audioUnit, kAudioUnitProperty_MaximumFramesPerSlice,
kAudioUnitScope_Global, 0, &framesPerSlice, &dataSize) == noErr
&& dataSize == sizeof (framesPerSlice) && static_cast<int> (framesPerSlice) != actualBufferSize)
{
actualBufferSize = static_cast<int> (framesPerSlice);
prepareFloatBuffers (actualBufferSize);
prepareFloatBuffers (framesPerSlice);
}
AudioUnitAddPropertyListener (audioUnit, kAudioUnitProperty_StreamFormat, handleStreamFormatChangeCallback, this);
return true;
}
@@ -744,6 +757,39 @@ private:
}
}
void handleStreamFormatChange()
{
AudioStreamBasicDescription desc;
zerostruct (desc);
UInt32 dataSize = sizeof (desc);
AudioUnitGetProperty(audioUnit,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
0,
&desc,
&dataSize);
if (desc.mSampleRate != getCurrentSampleRate())
{
updateSampleRateAndAudioInput();
const ScopedLock sl (callbackLock);
if (callback != nullptr)
{
callback->audioDeviceStopped();
callback->audioDeviceAboutToStart (this);
}
}
}
static void handleStreamFormatChangeCallback (void* device,
AudioUnit,
AudioUnitPropertyID,
AudioUnitScope scope,
AudioUnitElement element)
{
if (scope == kAudioUnitScope_Output && element == 0)
static_cast<iOSAudioIODevice*> (device)->handleStreamFormatChange();
}
JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice)
};


Loading…
Cancel
Save