Skip to content

Commit caf2102

Browse files
committed
iOS 18 audio bugfix
1 parent 9171032 commit caf2102

File tree

3 files changed

+27
-8
lines changed

3 files changed

+27
-8
lines changed

Superpowered/OpenSource/SuperpoweredIOSAudioIO.mm

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ static audioDeviceType NSStringToAudioDeviceType(NSString *str) {
1818
else return audioDeviceType_other;
1919
}
2020

21+
static unsigned int nearestPowerOfTwo(unsigned int n) {
22+
unsigned int v = n - 1;
23+
v |= v >> 1;
24+
v |= v >> 2;
25+
v |= v >> 4;
26+
v |= v >> 8;
27+
v |= v >> 16;
28+
v++;
29+
unsigned int x = v >> 1;
30+
return (v - n) > (n - x) ? x : v;
31+
}
32+
2133
// Initialization
2234
@implementation SuperpoweredIOSAudioIO {
2335
#if __has_feature(objc_arc)
@@ -307,7 +319,10 @@ - (void)onRouteChange:(NSNotification *)notification {
307319
}
308320

309321
- (void)applyBuffersize {
310-
[[AVAudioSession sharedInstance] setPreferredIOBufferDuration:double(preferredBufferSizeMs) * 0.001 error:NULL];
322+
double sr = double(self->samplerate);
323+
if (sr < 1000) sr = 48000.0;
324+
unsigned int powerOfTwoBufferSizeFrames = nearestPowerOfTwo((unsigned int)(sr * preferredBufferSizeMs * 0.001));
325+
[[AVAudioSession sharedInstance] setPreferredIOBufferDuration:powerOfTwoBufferSizeFrames / sr error:NULL];
311326
}
312327

313328
- (void)applySamplerate {
@@ -374,8 +389,8 @@ static void streamFormatChangedCallback(void *inRefCon, AudioUnit inUnit, AudioU
374389
if (self->samplerate != sr) {
375390
self->samplerate = sr;
376391
int minimum = int(self->samplerate * 0.001f), maximum = int(self->samplerate * 0.025f);
377-
self->minimumNumberOfFrames = (minimum >> 3) << 3;
378-
self->maximumNumberOfFrames = (maximum >> 3) << 3;
392+
self->minimumNumberOfFrames = nearestPowerOfTwo(minimum / 8) * 8;
393+
self->maximumNumberOfFrames = nearestPowerOfTwo(maximum / 8) * 8;
379394
if (self->maximumNumberOfFrames < 1024) self->maximumNumberOfFrames = 1024;
380395
if (self->minimumNumberOfFrames < 16) self->minimumNumberOfFrames = 16;
381396
[self performSelectorOnMainThread:@selector(applyBuffersize) withObject:nil waitUntilDone:NO];
@@ -504,7 +519,7 @@ - (void)setPreferredSamplerate:(int)hz {
504519
- (void)mapChannels {
505520
outputChannelMap.deviceChannels[0] = outputChannelMap.deviceChannels[1] = -1;
506521
for (int n = 0; n < 8; n++) outputChannelMap.HDMIChannels[n] = -1;
507-
for (int n = 0; n < 32; n++) outputChannelMap.USBChannels[n] = inputChannelMap.USBChannels[n] = - 1;
522+
for (int n = 0; n < 32; n++) outputChannelMap.USBChannels[n] = inputChannelMap.USBChannels[n] = -1;
508523

509524
if ([(NSObject *)self->delegate respondsToSelector:@selector(mapChannels:inputMap:externalAudioDeviceName:outputsAndInputs:)]) [delegate mapChannels:&outputChannelMap inputMap:&inputChannelMap externalAudioDeviceName:externalAudioDeviceName outputsAndInputs:audioSystemInfo];
510525
if (!audioUnit || (numberOfChannels <= 2)) return;

Superpowered/OpenSource/SuperpoweredOSXAudioIO.mm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ static void makeStreamFormat(AudioUnit au, AudioStreamBasicDescription *format,
214214

215215
static void setBufferSize(int samplerate, int preferredBufferSizeMs, AudioDeviceID deviceID) {
216216
if (samplerate < 1) return;
217-
UInt32 frames = powf(2.0f, floorf(log2f(float(samplerate) * 0.001f * float(preferredBufferSizeMs))));
217+
UInt32 frames = (UInt32)powf(2.0f, floorf(log2f(float(samplerate) * 0.001f * float(preferredBufferSizeMs))));
218218
if (frames > 4096) frames = 4096;
219219
AudioObjectPropertyAddress address = { kAudioDevicePropertyBufferFrameSize, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain };
220220
if (deviceID != UINT_MAX) AudioObjectSetPropertyData(deviceID, &address, 0, NULL, sizeof(UInt32), &frames);
@@ -277,7 +277,7 @@ - (void)createAudioUnits {
277277
AudioUnitAddPropertyListener(outau, kAudioUnitProperty_StreamFormat, streamFormatChangedCallback, (__bridge void *)self);
278278
AudioStreamBasicDescription format;
279279
makeStreamFormat(outau, &format, false, numberOfChannels);
280-
samplerate = format.mSampleRate;
280+
samplerate = (int)format.mSampleRate;
281281
if (!AudioUnitSetProperty(outau, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &format, sizeof(format))) {
282282
AURenderCallbackStruct callbackStruct;
283283
callbackStruct.inputProc = audioOutputCallback;
@@ -313,7 +313,7 @@ - (void)createAudioUnits {
313313
AudioUnitAddPropertyListener(inau, kAudioUnitProperty_StreamFormat, streamFormatChangedCallback, (__bridge void *)self);
314314
AudioStreamBasicDescription format;
315315
makeStreamFormat(inau, &format, true, numberOfChannels);
316-
if (outputEnabled) format.mSampleRate = samplerate; else samplerate = format.mSampleRate;
316+
if (outputEnabled) format.mSampleRate = samplerate; else samplerate = (int)format.mSampleRate;
317317
if (!AudioUnitSetProperty(inau, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, sizeof(format))) {
318318
AURenderCallbackStruct callbackStruct;
319319
callbackStruct.inputProc = audioInputCallback;

Superpowered/SuperpoweredAdvancedAudioPlayer.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,10 +385,14 @@ class AdvancedAudioPlayer {
385385

386386
/// @return Returns with the current pitch bend percent. Will be 1 if there is no pitch bend happening.
387387
JSWASM float getCurrentPitchBendPercent();
388-
388+
389389
/// @brief Reset the pitch bend offset to the beatgrid to zero.
390390
JSWASM void resetBendMsOffset();
391391

392+
/// @brief Set the pitch bend offset to the beatgrid.
393+
/// @param ms The value.
394+
JSWASM void setBendOffsetMs(double ms);
395+
392396
/// @return Indicates if returning from scratching or reverse playback will maintain the playback position as if the player had never entered into scratching or reverse playback.
393397
JSWASM bool isPerformingSlip();
394398

0 commit comments

Comments
 (0)