We discovered the iOS version is not the culprit. All models starting with 14 series iPhones and onward are affected by this problem, even on iOS 17. Must be some glitched interaction of hardware and software feature.
Affected models do not produce any audio, magnitude logging from C++ engine doesn't produce anything.
static OSStatus mixerPlaybackCallack(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) {
AudioEngine *self = (AudioEngine*)inRefCon;
uint32_t toget = inNumberFrames << 2;
//printf("mixerPlaybackCallack: bus: %u, frames: %u\n", (uint32_t)inBusNumber, (uint32_t)inNumberFrames);
if (inBusNumber < kMaxRemoteLines) {
auto& audiobuffer = self->m_remoteBuffers[inBusNumber];
int32_t len = 0;
if (uint8_t *buf = audiobuffer.tail(len)) {
int32_t tocopy = len > toget ? toget : len;
memcpy(ioData->mBuffers[0].mData, buf, tocopy);
audiobuffer.consume(tocopy);
if (tocopy < toget) {
memset(((uint8_t*)ioData->mBuffers[0].mData) + tocopy, 0, toget - tocopy);
}
} else {
memset((uint8_t*)ioData->mBuffers[0].mData, 0, toget);
*ioActionFlags |= kAudioUnitRenderAction_OutputIsSilence;
}
} else if (inBusNumber == kMaxRemoteLines+0) { // mike
AudioBufferList bufferList = {1, {2, toget, self->m_mikeBuf}}; // stereo, size - only necessary to get
AudioUnitRenderActionFlags tmpFlags = 0;
if (AudioUnitRender(self->m_remoteIoUnit, &tmpFlags, inTimeStamp, 1, inNumberFrames, &bufferList) == noErr) {
self->m_mikeBufSize = bufferList.mBuffers[0].mDataByteSize;
// ----------------------------------------------------------------------
// ✨ SIMPLIFIED MAGNITUDE LOGGING
// ----------------------------------------------------------------------
// Data is 16-bit PCM (SInt16) and stereo (2 channels)
int numChannels = 2;
int16_t *samples = (int16_t *)self->m_mikeBuf;
int numBytes = self->m_mikeBufSize;
int numSamples = numBytes / sizeof(int16_t);
long long magnitudeSum = 0;
if (samples && numSamples > 0) {
// Calculate the sum of absolute magnitudes
for (int i = 0; i < numSamples; ++i) {
magnitudeSum += std::abs(samples[i]);
}
// Calculate the average magnitude (Max is 32767)
double averageMagnitude = (double)magnitudeSum / numSamples;
// Log if the level is above a low threshold
static int callCount = 0;
if (averageMagnitude > 50.0) {
printf("🎤 INPUT DATA DETECTED! Frames: %u, Channels: %d, Avg Mag: %.2f\n",
(unsigned int)inNumberFrames, numChannels, averageMagnitude);
} else {
if (callCount % 100 == 0) {
printf("🎤 INPUT DATA CHECK: Frames: %u, Channels: %d, Avg Mag: %.2f (Silent)\n",
(unsigned int)inNumberFrames, numChannels, averageMagnitude);
}
callCount++;
}
}
// ----------------------------------------------------------------------
if (self->f) {
fwrite(bufferList.mBuffers[0].mData, 1, bufferList.mBuffers[0].mDataByteSize, self->f);
self->fsize += bufferList.mBuffers[0].mDataByteSize;
if (self->fsize > 10000000) {
fclose(self->f); self->f = nullptr;
}
}
self->m_echo.process(2, self->m_deviceSamplerate, (int16_t*)self->m_mikeBuf, (int16_t*)self->m_mikeBuf, inNumberFrames); // TEMPORARY DISABLED !!!!!!!!!!!!!!!
}