I have developed an audio play app in iOS with Objective-c and C language, it can play audio in most situations. But when I switch the app into background and then switch it back,it will not play the audio. Another problem is when I open it with earphone, if I take off the earphone, it will also stop play the audio.
The init function is:
- (instancetype)init {
self = [super init];
if (self) {
sysnLock = [[NSLock alloc] init];
if (_audioDescription.mSampleRate <= 0) {
_audioDescription.mSampleRate = _sampleRates;
_audioDescription.mFormatID = kAudioFormatLinearPCM;
_audioDescription.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
_audioDescription.mChannelsPerFrame = _channels;
_audioDescription.mFramesPerPacket = 1;
_audioDescription.mBitsPerChannel = 16;
_audioDescription.mBytesPerFrame = (_audioDescription.mBitsPerChannel / 8) * _audioDescription.mChannelsPerFrame;
_audioDescription.mBytesPerPacket = _audioDescription.mBytesPerFrame * _audioDescription.mFramesPerPacket;
}
AudioQueueNewOutput(&_audioDescription, AudioPlayerCallback, (__bridge void *_Nullable)(self), nil, 0, 0,
&audioQueue);
AudioQueueSetParameter(audioQueue, kAudioQueueParam_Volume, 100.0);
for (int i = 0; i < QUEUE_BUFFER_SIZE; i++) {
audioQueueBufferUsed[i] = false;
osState = AudioQueueAllocateBuffer(audioQueue, MIN_SIZE_PER_FRAME, &audioQueueBuffers[i]);
}
osState = AudioQueueStart(audioQueue, NULL);
}
return self;
}
In which AudioPlayerCallback is a callback function to reset the audioBufferUsed.
And the audio play function is:
- (void)startPlay:(AudioData *)audioData {
uint8_t *c_data = get_data(audioData);
size_t c_data_size = get_data_size(audioData);
[sysnLock lock];
int i = 0;
while (true) {
if (!audioQueueBufferUsed[i]) {
audioQueueBufferUsed[i] = true;
break;
} else {
i++;
if (i >= QUEUE_BUFFER_SIZE) {
i = 0;
}
}
}
audioQueueBuffers[i]->mAudioDataByteSize = (unsigned int)c_data_size;
memcpy(audioQueueBuffers[i]->mAudioData, c_data, c_data_size);
AudioQueueEnqueueBuffer(audioQueue, audioQueueBuffers[i], 0, NULL);
OSStatus status = AudioQueueStart(audioQueue, NULL);
[sysnLock unlock];
}
In which get_data and get_data_size can get the uint_8 data and its size to play.
You will setup
NotificationCenterto observe the following keysAVAudioSessionInterruptionNotificationandAVAudioSessionRouteChangeNotificationIn classic coding style you don't forget to remove the observer in your dealloc method.
This will allow you to watch when your disturbing events happen and act accordingly with re-creation of your AudioQueue, Start, Stop, Buffer if needed.
Another way is to observe changes of propertys of the AudioQueueBuffer API with...