Files: 6c0343ff56f76e49059e1846db515584125768f3 / src / audio_output.cpp
2248 bytesRaw
1 | |
2 | |
3 | static const uint32_t DEFAULT_CHUNK_MS = 60; |
4 | |
5 | CoreAudioStream::CoreAudioStream(callback useCb, void * userData, const uint32_t useSampleRate) : |
6 | playerCallback(useCb), playerCallbackUserData(userData), |
7 | sampleRate(useSampleRate), audioQueue(NULL) |
8 | { |
9 | const uint32_t bufferSize = 2048; |
10 | const uint32_t audioLatencyFrames = sampleRate * DEFAULT_CHUNK_MS / 1000; |
11 | bufferByteSize = bufferSize << 2; |
12 | // Number of buffers should be ceil(audioLatencyFrames / bufferSize) |
13 | numberOfBuffers = (audioLatencyFrames + bufferSize - 1) / bufferSize; |
14 | buffers = new AudioQueueBufferRef[numberOfBuffers]; |
15 | } |
16 | |
17 | CoreAudioStream::~CoreAudioStream() { |
18 | close(); |
19 | delete[] buffers; |
20 | } |
21 | |
22 | void CoreAudioStream::renderOutputBuffer(void *userData, AudioQueueRef queue, AudioQueueBufferRef buffer) { |
23 | CoreAudioStream *stream = (CoreAudioStream *)userData; |
24 | if (queue == NULL) { |
25 | // Priming the buffers, skip timestamp handling |
26 | queue = stream->audioQueue; |
27 | } |
28 | |
29 | uint frameCount = buffer->mAudioDataByteSize >> 2; |
30 | stream->playerCallback(stream->playerCallbackUserData, (short*)buffer->mAudioData, frameCount); |
31 | |
32 | AudioQueueEnqueueBuffer(queue, buffer, 0, NULL); |
33 | } |
34 | |
35 | bool CoreAudioStream::start() { |
36 | if (audioQueue != NULL) { |
37 | return true; |
38 | } |
39 | |
40 | AudioStreamBasicDescription dataFormat = {sampleRate, kAudioFormatLinearPCM, kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian, 4, 1, 4, 2, 16, 0}; |
41 | OSStatus res = AudioQueueNewOutput(&dataFormat, renderOutputBuffer, this, NULL, NULL, 0, &audioQueue); |
42 | if (res || audioQueue == NULL) { |
43 | return false; |
44 | } |
45 | |
46 | for (uint i = 0; i < numberOfBuffers; i++) { |
47 | res = AudioQueueAllocateBuffer(audioQueue, bufferByteSize, buffers + i); |
48 | if (res || buffers[i] == NULL) { |
49 | res = AudioQueueDispose(audioQueue, true); |
50 | audioQueue = NULL; |
51 | return false; |
52 | } |
53 | buffers[i]->mAudioDataByteSize = bufferByteSize; |
54 | // Prime the buffer allocated |
55 | renderOutputBuffer(this, NULL, buffers[i]); |
56 | } |
57 | |
58 | res = AudioQueueStart(audioQueue, NULL); |
59 | if (res) { |
60 | res = AudioQueueDispose(audioQueue, true); |
61 | audioQueue = NULL; |
62 | return false; |
63 | } |
64 | |
65 | return true; |
66 | } |
67 | |
68 | void CoreAudioStream::close() { |
69 | if (audioQueue == NULL) return; |
70 | OSStatus res = AudioQueueDispose(audioQueue, true); |
71 | audioQueue = NULL; |
72 | } |
73 |
Built with git-ssb-web