Native player for iOS, using AVAudioPlayer is easy,
Take the audio resource file path, create AVAudioPlayer,
And prepareToPlay, it’s ready to play
Using AudioToolbox to develop local player of C program, the routine is also very simple
Play in 3 steps:
1. Get the audio file and create a new audio output queue
Given a local resource path URL, use AudioFileOpenURL to obtain the audio file AudioFileID
Using AudioQueueNewOutput, create audio output queue AudioQueueRef
With AudioToolbox, output is playback, AudioQueueNewOutput
The input is the recording, AudioQueueNewInput
2, if you want to play, you usually allocate 3 buffers AudioQueueBufferRef, and you’re ready to go
Using the AudioQueueAllocateBuffer, allocate three audio data buffers, AudioQueueBufferRef
One buffer for playback, one buffer for injecting audio data,
There is also a buffer for preparation and to prevent lag
Using AudioQueueStart, the audio queue output,
The output is playing
3. Input audio file data into the output queue during callback processing
Mainly through the following two methods:
Take out the data
AudioFileReadPacketData
Inject the data into the output queue
AudioQueueEnqueueBuffer
Stop playing. One step
AudioQueueStop
Copy the code
Key points:
1. The C program player developed by AudioToolbox is a simple structure
Struct Player {// Corresponding audio file var playbackFile: AudioFileID? Start position var packetPosition: Int64 = 0 start position var packetPosition: Int64 = 0 UInt32 = 0 use ASPD var packetDescs: / / may be UnsafeMutablePointer < AudioStreamPacketDescription >? Var isDone = false}Copy the code
- The first property, which is easy to understand, represents an audio resource file
When an audio file is opened, it is represented by an AudioFileID
-
And the last property, it’s easy to understand, is the file finished playing.
-
The penultimate property, ASPD, might use,
The data format of audio, that is, the encoding format of audio, is mainly divided into compressed and uncompressed,
Uncompressed data, using ASBD, the calculation is relatively simple,
Compression data, ASBD is not enough, plus ASPD
If ASPD isn’t enough, add magic cookies
- The remaining two properties, which are mainly used in playback callbacks,
In the callback method of the output queue
PacketPosition, where is the current playing
NumPacketsToRead, which indicates that several data will be injected at this time
2. Output queue callback method
Here, take the data from the audio file,
Inject data into the allocated 3 blank buffers,
Give it to the playback queue to play
There are a lot of Pointers here
Unsafe, even if you want to use a pointer. Apple plus Unsafe, that’s boring
The thing to keep in mind is,
Start Position (packetPosition), length (numPacketsToRead),
After injection of queue, start the position changed, forward nPackets (player. Pointee. NumPacketsToRead)
There is no data, nPackets is 0, it is the end of playing
func outputCallback(userData: UnsafeMutableRawPointer? , queue: OpaquePointer, bufferToFill: UnsafeMutablePointer<AudioQueueBuffer>) { guard let user = userData else { return } let player = user.assumingMemoryBound(to: Player.self) if player.pointee.isDone { return } var numBytes: UInt32 = bufferToFill.pointee.mAudioDataBytesCapacity var nPackets = player.pointee.numPacketsToRead Utility.check(error: AudioFileReadPacketData(player.pointee.playbackFile! , false, &numBytes, player.pointee.packetDescs, player.pointee.packetPosition, &nPackets, bufferToFill.pointee.mAudioData), operation: "AudioFileReadPacketData failed") if nPackets > 0 { bufferToFill.pointee.mAudioDataByteSize = numBytes Utility.check(error: AudioQueueEnqueueBuffer(queue, // queue bufferToFill, // buffer to enqueue (player.pointee.packetDescs == nil ? Zero: nPackets), // number of packet descriptions player.pointee.packetDescs), // pointer to a PacketDescriptions array operation: "AudioQueueEnqueueBuffer failed") player.pointee.packetPosition += Int64(nPackets) } else { Utility.check(error: AudioQueueStop(queue, false), operation: "AudioQueueStop failed") player.pointee.isDone = true } }Copy the code
As you can see, Apple’s AVAudioPlayer is simply a state wrapper,
We’re still using AudioToolbox