-
-
Notifications
You must be signed in to change notification settings - Fork 337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
iOS: Capture device cannot be initialized or is initialized with NULL backend #868
Comments
pContext->coreaudio.AudioUnitInitialize
fails with kAudioFormatUnsupportedDataFormatError
So, I've made more tests reducing all possible variables and simplifying the test case. First of all, I created a simple app in Xcode from scratch using ObjC (not using Switft) and then added miniaudio in the source directory. I've then modified the ViewController.m like this (please ignore any potential ObjC ugliness, I'm not very well versed in either iOS development or ObjC): #import "ViewController.h"
#define MA_DEBUG_OUTPUT
#define MA_NO_RUNTIME_LINKING
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
bool init = false;
ma_device device;
ma_device_config config;
ma_waveform_config sineWaveConfig;
ma_waveform sineWave;
ma_context context;
ma_device capture_device;
ma_device_config capture_config;
void data_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
{
ma_waveform* pSineWave;
MA_ASSERT(pDevice->playback.channels == 2);
pSineWave = (ma_waveform*)pDevice->pUserData;
MA_ASSERT(pSineWave != NULL);
ma_waveform_read_pcm_frames(pSineWave, pOutput, frameCount, NULL);
(void)pInput; /* Unused. */
}
void capture_callback(ma_device* pDevice, void* pOutput, const void* pInput, ma_uint32 frameCount)
{
float* input = (float*)pInput;
float acc = 0;
for(uint32_t i = 0; i < frameCount; i++) {
acc += input[i];
}
float avg = acc / frameCount;
}
@interface ViewController ()
@end
@implementation ViewController
- (void)buttonPressed: (UIButton*)button {
NSLog(@"Button pressed");
if(init) {
//ma_device_uninit(&device);
ma_device_uninit(&capture_device);
NSLog(@"Uninit device");
init = false;
return;
}
/*if(ma_context_init(NULL, 0, NULL, &context) != MA_SUCCESS) {
NSLog(@"Error initializing context");
return;
}*/
/*config = ma_device_config_init(ma_device_type_playback);
config.playback.format = ma_format_f32;
config.playback.channels = 2;
config.dataCallback = data_callback;
config.sampleRate = 48000;
config.pUserData = &sineWave;
if (ma_device_init(&context, &config, &device) != MA_SUCCESS) {
printf("Failed to open playback device.\n");
return;
}
printf("Playback Device Name: %s\n", device.playback.name);
sineWaveConfig = ma_waveform_config_init(device.playback.format, device.playback.channels, device.sampleRate, ma_waveform_type_sine, 0.2, 220);
ma_waveform_init(&sineWaveConfig, &sineWave);
if (ma_device_start(&device) != MA_SUCCESS) {
printf("Failed to start playback device.\n");
ma_device_uninit(&device);
return;
}
*/
capture_config = ma_device_config_init(ma_device_type_capture);
capture_config.capture.format = ma_format_f32;
capture_config.dataCallback = capture_callback;
ma_result res = ma_device_init(NULL /* &context */, &capture_config, &capture_device);
if(res != MA_SUCCESS) {
NSLog(@"Capture init error: %s", ma_result_description(res));
return;
}
printf("Capture Device Name: %s\n", capture_device.capture.name);
if(ma_device_start(&capture_device)!= MA_SUCCESS) {
NSLog(@"Error starting capture device");
return;
}
init = true;
}
- (void)permButtonPressed: (UIButton*)button {
[AVAudioApplication requestRecordPermissionWithCompletionHandler:^(bool res){
NSLog(@"Granted: %d", res);
}];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:@"Init" forState:UIControlStateNormal];
[button sizeToFit];
button.center = CGPointMake(50, 150);
[button addTarget:self action:@selector(buttonPressed:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
UIButton *perm = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[perm setTitle:@"Permission" forState:UIControlStateNormal];
[perm sizeToFit];
perm.center = CGPointMake(50, 250);
[perm addTarget:self action:@selector(permButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:perm];
}
@end (once again, I set permissions with As you can see from the commented out code I've tried both the original approach (one context, two devices) and a simpler approach (single capture device without context). The former yields the same results as previously described in the older comment (Unknown error and everything), while the latter has a different outcome (here's the log):
The device can be initialized correctly but with the wrong backend I believe, so it results in empty incoming audio. What is interesting is the error I also would have liked to test with a real device but unfortunately I don't really have access to an iPhone at the moment, so when I'll get it I will do some more tests. Edit: I also forgot to add that the playback works fine, the issue is only present with capture. Update: I've confirmed this issue only happens with iOS devices, while on MacOS everything works fine. |
pContext->coreaudio.AudioUnitInitialize
fails with kAudioFormatUnsupportedDataFormatError
Sorry for not getting back to you on this. Unfortunately I'm not going to have a satisfying answer for you. I don't know what's going on here. Certainly your simplified code in your original comment should work. The falling back to the NULL backend is expected - that's just standard fallback functionality. The fact that it's happening on a simulator is encouraging because at least then I have a chance of reproducing it myself. But I rarely dig out my MacBook, and I'm certainly no iOS expert (I lean heavily on the community for advice) so no timeframe on when I'll get to this one. |
UPDATE: the title was updated in light of the second comment which simplifies the problem, though the two scenarios still seem to be related. Read both for context.
I wasn't sure if this was the right place to ask, but it seems to be an issue within miniaudio.
The problem occurs when using
ma_device_init
on a device with typema_device_type_capture
on the iOS simulator (iOS 17.2). Here's the code:All the configuration options are commented out but they don't make any difference. Initially the call falls with MA_ERROR: with some debugging, I've found the issue to be originating from here:
The problem here is in
pContext->coreaudio.AudioUnitInitialize
which fails withkAudioFormatUnsupportedDataFormatError
(or similar, the error is 1819304813 which on ossstatus.com is reported as that - I don't know much about iOS development so this may be wrong). Adding some debug print statements I got these values forbestFormat
:Changing the parameters such as number of channels or sample rate does not change any of the above variables. If I understand correctly, this should be the correct behavior on iOS (as far as I understood from reading the code).
Looking through the issues I found #804 which seems to be related, even though I've basically stripped out everything from my code leaving essentially just the example provided above (context is still initialized properly and everything). Initializing playback devices works perfectly and it's in fact what I was doing before (same as #804, I have two separate devices initialized within the same context). I tried different formats and sample rates with no success. What could be the issue? Am I doing something wrong?
Microphone permissions are also granted.
The text was updated successfully, but these errors were encountered: