Re: iOS 13 is not bit-accurate; previous versions were
Re: iOS 13 is not bit-accurate; previous versions were
- Subject: Re: iOS 13 is not bit-accurate; previous versions were
- From: Andrew Smith via Coreaudio-api <email@hidden>
- Date: Tue, 26 May 2020 13:30:04 -0700
Brian,
I’ve tried both allow mixing with other audio, and not, both work the same.
I’m using the remote IO framework, and I will paste my main setup code below.
One interesting thing that I’ve found is that if I select playback only mode,
it works fine! The audio data passes through to the USB output device unaltered
and the surround files play fine. It’s just when I add in record mode (using
[avSession setCategory:AVAudioSessionCategoryPlayAndRecord mode:mode
options:options error:&err]) that the output audio is no longer bit-accurate. I
do need record and play for audio analysis of the input. Again this is only
under iOS 13, older iOS work fine.
Best,
Andrew Smith
In this code sample rate is always 48k and numChannels = 2. This is just copied
from other sources and may certainly have issues! One thing I find weird is
that I have to reverse the output busses when I apply the formats, ie I have to
apply the playback format to the input bus.
#define kOutputBus 0
#define kInputBus 1
OSStatus status;
// Describe audio component
AudioComponentDescription desc;
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_RemoteIO;
desc.componentFlags = 0;
desc.componentFlagsMask = 0;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
// Get component
AudioComponent inputComponent = AudioComponentFindNext(NULL, &desc);
// Get audio units
status = AudioComponentInstanceNew(inputComponent, &inRemoteIOUnitAV);
[AvHelper checkStatus:status msg:@"AudioComponentInstanceNew"];
UInt32 flag = 1;
// Enable IO for playback
status = AudioUnitSetProperty(inRemoteIOUnitAV,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Output,
kOutputBus,
&flag,
sizeof(flag));
[AvHelper checkStatus:status msg:@"AudioUnitSetProperty 2"];
// Enable IO for recording
status = AudioUnitSetProperty(inRemoteIOUnitAV,
kAudioOutputUnitProperty_EnableIO,
kAudioUnitScope_Input,
kInputBus,
&flag,
sizeof(flag));
[AvHelper checkStatus:status msg:@"AudioUnitSetProperty 1"];
// Describe format
int numChannels = 2;
AudioStreamBasicDescription audioFormat;
audioFormat.mSampleRate = auSampleRate;
audioFormat.mFormatID = kAudioFormatLinearPC
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger |
kAudioFormatFlagIsPacked;
audioFormat.mBytesPerPacket = 2 * numChannels;
audioFormat.mFramesPerPacket = 1;
audioFormat.mBytesPerFrame = 2 * numChannels;
audioFormat.mChannelsPerFrame = numChannels;
audioFormat.mBitsPerChannel = 16;
audioFormat.mReserved = 0;
// Apply format
status = AudioUnitSetProperty(inRemoteIOUnitAV,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Output,
kInputBus,
&audioFormat,
sizeof(audioFormat));
[AvHelper checkStatus:status msg:@"AudioUnitSetProperty 3"];
status = AudioUnitSetProperty(inRemoteIOUnitAV,
kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input,
kOutputBus,
&audioFormat,
sizeof(audioFormat));
[AvHelper checkStatus:status msg:@"AudioUnitSetProperty 4"];
// Set input callback
AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc = inRenderProc.inputProc;
callbackStruct.inputProcRefCon = inRenderProc.inputProcRefCon;
status = AudioUnitSetProperty(inRemoteIOUnitAV,
kAudioOutputUnitProperty_SetInputCallback,
kAudioUnitScope_Global,
kInputBus,
&callbackStruct,
sizeof(callbackStruct));
[AvHelper checkStatus:status msg:@"AudioUnitSetProperty 5"];
// Set output callback
callbackStruct.inputProc = outRenderProc.inputProc;
callbackStruct.inputProcRefCon = outRenderProc.inputProcRefCon;
status = AudioUnitSetProperty(inRemoteIOUnitAV,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Global,
kOutputBus,
&callbackStruct,
sizeof(callbackStruct));
[AvHelper checkStatus:status msg:@"AudioUnitSetProperty 6"];
// Disable buffer allocation for the recorder (optional - do this if we
want to pass in our own)
flag = 0;
status = AudioUnitSetProperty(inRemoteIOUnitAV,
kAudioUnitProperty_ShouldAllocateBuffer,
kAudioUnitScope_Output,
kInputBus,
&flag,
sizeof(flag));
> On May 21, 2020, at 10:18 PM, Brian Willoughby <email@hidden>
> wrote:
>
> On macOS, there was a way to "hog" the audio interface so that no other
> application's audio would be mixed in. Even at the same sample rate, mixing
> anything with a surround-encoded stream would destroy it.
>
> Are you already using anything like this? If so, and Apple broke it, then
> that's one thing. If Apple doesn't offer "hog" mode on iOS, then you might
> need to look for another way to take full control of the stream. I haven't
> written audio code for iOS in years, but I recall that applications can mark
> themselves as input-only, output-only, input and output, and various other
> categories. Perhaps there is a category to say that you need un-manipulated
> streams.
>
> The audio objects seem to keep changing, but there are usually way to query
> your stream type, the stream type out the output unit, and to do that for the
> input, output, and perhaps even global scopes (I think global scope is the
> only one that doesn't have a stream type).
>
> Sorry I don't have an immediate answer, but maybe you can give us a few more
> details on which audio object frameworks you're using, and perhaps the
> results of some code-based queries of the output stream formats.
>
> Brian Willoughby
>
>
> On May 21, 2020, at 4:00 PM, Andrew Smith via Coreaudio-api
> <email@hidden <mailto:email@hidden>> wrote:
>> I’m the developer of AudioTools, over 10 years on the app store, lots of
>> audio test & measurement functions. One in particular is a 5.1 surround
>> signal generator, which works with our own hardware device,
>> iAudioInterface2, which happens to have a Toslink digital audio output
>> connector. The idea is that I pre-encode surround signal audio files in the
>> Dolby Digital 5.1 format, open the file in the app, and break the data into
>> packets that get formatted to Dolby specs and sent out the Toslink connector
>> at 48k sample rate. Surprisingly, this actually works. For many years it
>> has, anyway. I can send out a pink noise signal to a particular channel, or
>> send an encoded music file out to the system. I am using basic remote IO
>> audio processing here. Despite many years in audio and DSP I do not consider
>> myself an iOS guru, I just use a simple set of iOS tools that seem to work.
>>
>> Starting with iOS 13 however, the surround signal generator no longer works.
>> This scheme relies on the signal (data) not being altered by iOS at all, it
>> must be sent through unaltered, as bit-accurate audio. In 13, I get just
>> random noise, while the same app on iOS 11 or 12 outputs the surround data
>> correctly. My guess is that Apple has inserted a sample rate converter, even
>> though as far as I can tell the hardware is still running at 48k, and I am
>> requesting 48k. I’ve posted a bug report to Apple but unsurprisingly I’ve
>> had no response to it since I am likely the only person on Earth who cares
>> about this. Any ideas on something to try or if perhaps anyone else has
>> knowledge about this I would highly appreciate it!
>>
>> Best,
>> Andrew Smith
>
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden