Skip to content

Commit 6089c3b

Browse files
dsward2dsward2
authored andcommitted
In AudioMonitor convertBuffer - the method that resamples the audio data to 48000 Hz - if TPCircularBufferProduceBytes indicates an error, it is probably due to a buffer overrun about to occur because the ring buffer space is depleted (possibly due to missed TPCircularBufferConsume getting missed somewhere?).
When the buffer overrun situation is detected, the method will clear the circular buffer and call TPCircularBufferProduceBytes to try to write to the buffer again. This seems to work, although it is not the recommended practice.
1 parent fa33b21 commit 6089c3b

1 file changed

Lines changed: 20 additions & 59 deletions

File tree

AudioMonitor/AudioMonitor/AudioMonitor.mm

Lines changed: 20 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@
3232
#define kAudioQueueSampleRate 48000
3333

3434
#define kInputPacketLength sizeof(SInt16)
35-
//#define kInputBufferLength (kInputMaxPackets * kInputPacketLength)
36-
37-
//#define kOutputPacketLength sizeof(SInt16)
38-
//#define kOutputBufferLength (kInputMaxPackets * kOutputPacketLength)
3935

4036
#define kAudioQueueBufferSize (kInputMaxPackets * sizeof(SInt16) * 2)
4137

@@ -85,7 +81,6 @@ - (void)runInputBufferOnThread
8581
NSTimeInterval lastReadTime = [NSDate timeIntervalSinceReferenceDate] + 20;
8682
NSTimeInterval nextTimeoutReportInterval = 5;
8783

88-
//int32_t circularBufferLength = 512 * 1024;
8984
int32_t circularBufferLength = 256 * 1024;
9085
TPCircularBufferInit(&inputCircularBuffer, circularBufferLength);
9186

@@ -141,21 +136,18 @@ - (void)runInputBufferOnThread
141136

142137
// copy RTL-SDR LPCM data to a circular buffer to be used as input for AudioConverter process
143138

144-
int32_t space;
145-
void *ptr = TPCircularBufferHead(&inputCircularBuffer, &space);
146-
//NSLog(@"AudioMonitor runInputBufferOnThread Produce, bytesAvailableCount=%u, space = %d, head = %p", bytesAvailableCount, space, ptr);
139+
//int32_t space;
140+
//void *ptr = TPCircularBufferHead(&inputCircularBuffer, &space); // for NSLog below
147141

148142
bool produceBytesResult = TPCircularBufferProduceBytes(&inputCircularBuffer, rtlsdrBuffer, bytesAvailableCount);
149143

150144
if (produceBytesResult == false)
151145
{
152146
TPCircularBufferClear(&inputCircularBuffer);
153147

154-
NSLog(@"AudioMonitor runInputBufferOnThread Produce, bytesAvailableCount=%u, space = %d, head = %p", bytesAvailableCount, space, ptr);
148+
//NSLog(@"AudioMonitor runInputBufferOnThread Produce, bytesAvailableCount=%u, space = %d, head = %p", bytesAvailableCount, space, ptr);
155149
NSLog(@"AudioMonitor runInputBufferOnThread - produce bytes failed, bytesAvailableCount = %d", bytesAvailableCount);
156150
}
157-
158-
//fwrite(rtlsdrBuffer, 1, bytesAvailableCount, stdout); // also write to stdout at original sampling rate, for sox, etc.
159151
}
160152

161153
free(rtlsdrBuffer);
@@ -184,9 +176,6 @@ - (void)runInputBufferOnThread
184176

185177
packetIndex++;
186178
}
187-
188-
//NSLog(@"AudioMonitor exit");
189-
//fprintf(stderr, "AudioMonitor exit\n");
190179
}
191180

192181

@@ -203,7 +192,6 @@ - (void)runAudioConverterOnThread
203192
NSTimeInterval lastReadTime = [NSDate timeIntervalSinceReferenceDate] + 20;
204193
NSTimeInterval nextTimeoutReportInterval = 5;
205194

206-
//int32_t circularBufferLength = 256 * 1024;
207195
int32_t circularBufferLength = 128 * 1024;
208196
TPCircularBufferInit(&audioConverterCircularBuffer, circularBufferLength);
209197

@@ -227,10 +215,6 @@ - (void)runAudioConverterOnThread
227215

228216
if( bytesAvailableCount <= 0)
229217
{
230-
//[NSThread sleepForTimeInterval:0.01f];
231-
232-
//TPCircularBufferClear(&inputCircularBuffer);
233-
234218
usleep(1000);
235219
}
236220
else
@@ -242,18 +226,11 @@ - (void)runAudioConverterOnThread
242226

243227
//NSLog(@"AudioMonitor sending data, length=%ld", bytesAvailableCount);
244228

245-
//if (self.volume > 0.0f)
246-
//{
247-
// [self convertBuffer:circularBufferDataPtr length:bytesAvailableCount];
248-
//}
249-
250229
[self convertBuffer:circularBufferDataPtr length:bytesAvailableCount];
251230

252231
//NSLog(@"AudioMonitor runAudioConverterOnThread - Consume bytesAvailableCount = %d, circularBufferDataPtr = %p", bytesAvailableCount, circularBufferDataPtr);
253232

254233
TPCircularBufferConsume(&inputCircularBuffer, bytesAvailableCount);
255-
256-
////fwrite(&inputCircularBuffer, 1, bytesAvailableCount, stdout); // also write to stdout at original sampling rate, for sox, etc.
257234
}
258235
}
259236

@@ -372,25 +349,6 @@ - (void)runAudioQueueOnThread
372349
}
373350
}
374351

375-
/*
376-
bool mIsRunning = true;
377-
378-
do {
379-
CFRunLoopRunInMode (
380-
kCFRunLoopDefaultMode,
381-
0.1,
382-
false // returnAfterSourceHandled
383-
);
384-
} while (mIsRunning == true);
385-
386-
// After the audio queue has stopped, runs the run loop a bit longer to ensure that the audio queue buffer currently playing has time to finish
387-
CFRunLoopRunInMode (
388-
kCFRunLoopDefaultMode,
389-
1,
390-
false
391-
);
392-
*/
393-
394352
CFRunLoopRun();
395353
}
396354

@@ -438,8 +396,6 @@ void audioQueueCallback(void *custom_data, AudioQueueRef queue, AudioQueueBuffer
438396
}
439397
}
440398

441-
//fwrite(circularBufferDataPtr, sizeof(SInt16), samplesCount, stdout); // also write resampled audio to stdout, perhaps for sox, etc.
442-
443399
buffer->mAudioDataByteSize = channelOutputBytes;
444400

445401
if (self.volume > 0.0f)
@@ -467,8 +423,6 @@ void audioQueueCallback(void *custom_data, AudioQueueRef queue, AudioQueueBuffer
467423

468424
memset(buffer->mAudioData, 0, buffer->mAudioDataByteSize);
469425

470-
//fwrite(buffer->mAudioData, 1, buffer->mAudioDataByteSize, stdout); // also write silent audio to stdout, perhaps for sox, etc.
471-
472426
if (self.volume > 0.0f)
473427
{
474428
// output silent audio to the current system device
@@ -515,8 +469,8 @@ - (void)convertBuffer:(void *)inputBufferPtr length:(UInt32)dataLength
515469

516470
//NSLog(@"AudioMonitor convertBuffer numFrames=%d, remain=%d", numFrames, audioConverterInputPacketsRemain);
517471

518-
// for up-sampling (e.g., 10000 Hz to 41000 Hz), AudioConverterFillComplexBuffer was not making multiple calls to inputProc,
519-
// so try multiple calls in a loop here and check result for exit condition 'zero' indicating end of input buffer.
472+
// for up-sampling (e.g., 10000 Hz to 41000 Hz), use multiple calls to AudioConverterFillComplexBuffer
473+
// in a loop here and check result for exit condition 'zero' indicating end of input buffer.
520474
// Down-sampling (e.g. 85000 Hz to 10000 Hz) seems to get the buffer processed without the loop.
521475

522476
OSStatus convertResult = noErr;
@@ -542,22 +496,29 @@ - (void)convertBuffer:(void *)inputBufferPtr length:(UInt32)dataLength
542496

543497
void * convertedDataPtr = audioConverterOutputBufferList.mBuffers[0].mData;
544498

545-
int32_t space;
546-
void *ptr = TPCircularBufferHead(&audioConverterCircularBuffer, &space);
547-
//NSLog(@"AudioMonitor convertBuffer Produce convertedDataLength = %d, space = %d, head = %p", convertedDataLength, space, ptr);
548-
549-
bool produceBytesResult = TPCircularBufferProduceBytes(&audioConverterCircularBuffer, convertedDataPtr, convertedDataLength);
499+
//int32_t space;
500+
//void *ptr = TPCircularBufferHead(&audioConverterCircularBuffer, &space); // for NSLog below
550501

551502
fwrite(convertedDataPtr, 1, convertedDataLength, stdout); // also write resampled audio to stdout, perhaps for sox, etc.
503+
504+
bool produceBytesResult = TPCircularBufferProduceBytes(&audioConverterCircularBuffer, convertedDataPtr, convertedDataLength);
552505

553506
if (produceBytesResult == false)
554507
{
555-
// TODO: We are dropping packets here to avoid buffer overrun, is audioConverterCircularBuffer missing consume operations?
508+
// TODO: We are here to avoid buffer overrun, is TPCircularBufferConsume for audioConverterCircularBuffer getting missed somewhere?
556509

510+
// clear buffer and try again (not recommended practice)
557511
TPCircularBufferClear(&(self->audioConverterCircularBuffer));
512+
513+
produceBytesResult = TPCircularBufferProduceBytes(&audioConverterCircularBuffer, convertedDataPtr, convertedDataLength);
558514

559-
NSLog(@"AudioMonitor convertBuffer Produce convertedDataLength = %d, space = %d, head = %p", convertedDataLength, space, ptr);
560-
NSLog(@"AudioMonitor convertBuffer - produce bytes failed, convertedDataLength = %d", convertedDataLength);
515+
if (produceBytesResult == false)
516+
{
517+
// If we get here, packets will be dropped
518+
519+
//NSLog(@"AudioMonitor convertBuffer Produce convertedDataLength = %d, space = %d, head = %p", convertedDataLength, space, ptr);
520+
NSLog(@"AudioMonitor convertBuffer - produce bytes failed, convertedDataLength = %d", convertedDataLength);
521+
}
561522
}
562523
}
563524

0 commit comments

Comments
 (0)