58 |
// let all connected engines render 'fragmentSize' sample points |
// let all connected engines render 'fragmentSize' sample points |
59 |
pAqData->pDevice->RenderAudio(bufferSize); |
pAqData->pDevice->RenderAudio(bufferSize); |
60 |
|
|
61 |
int16_t* pDataBuf = (int16_t*)(inBuffer->mAudioData); |
Float32* pDataBuf = (Float32*)(inBuffer->mAudioData); |
62 |
|
|
63 |
uint uiCoreAudioChannels = pAqData->pDevice->uiCoreAudioChannels; |
uint uiCoreAudioChannels = pAqData->pDevice->uiCoreAudioChannels; |
|
// convert from DSP value range (-1.0..+1.0) to 16 bit integer value |
|
|
// range (-32768..+32767), check clipping and copy to Alsa output buffer |
|
64 |
for (int c = 0; c < uiCoreAudioChannels; c++) { |
for (int c = 0; c < uiCoreAudioChannels; c++) { |
65 |
float* in = pAqData->pDevice->Channels[c]->Buffer(); |
float* in = pAqData->pDevice->Channels[c]->Buffer(); |
66 |
for (int i = 0, o = c; i < bufferSize; i++ , o += uiCoreAudioChannels) { |
for (int i = 0, o = c; i < bufferSize; i++ , o += uiCoreAudioChannels) { |
67 |
float sample_point = in[i] * 32768.0f; |
pDataBuf[o] = in[i]; |
|
if (sample_point < -32768.0) sample_point = -32768.0; |
|
|
if (sample_point > 32767.0) sample_point = 32767.0; |
|
|
pDataBuf[o] = (int16_t) sample_point; |
|
68 |
} |
} |
69 |
} |
} |
70 |
|
|
71 |
inBuffer->mAudioDataByteSize = (uiCoreAudioChannels * 2) * bufferSize; |
inBuffer->mAudioDataByteSize = (uiCoreAudioChannels * 4) * bufferSize; |
72 |
|
|
73 |
OSStatus res = AudioQueueEnqueueBuffer(pAqData->mQueue, inBuffer, 0, NULL); |
OSStatus res = AudioQueueEnqueueBuffer(pAqData->mQueue, inBuffer, 0, NULL); |
74 |
if(res) std::cerr << "AudioQueueEnqueueBuffer: Error " << res << std::endl; |
if(res) std::cerr << "AudioQueueEnqueueBuffer: Error " << res << std::endl; |
102 |
CurrentDevice = CAAudioDeviceListModel::GetModel()->GetOutputDevice(device); |
CurrentDevice = CAAudioDeviceListModel::GetModel()->GetOutputDevice(device); |
103 |
CurrentDevice.AddListener(this); |
CurrentDevice.AddListener(this); |
104 |
|
|
105 |
|
memset (&aqPlayerState.mDataFormat, 0, sizeof(AudioStreamBasicDescription)); |
106 |
|
|
107 |
aqPlayerState.mDataFormat.mSampleRate = samplerate; |
aqPlayerState.mDataFormat.mSampleRate = samplerate; |
108 |
aqPlayerState.mDataFormat.mFormatID = kAudioFormatLinearPCM; |
aqPlayerState.mDataFormat.mFormatID = kAudioFormatLinearPCM; |
109 |
|
|
110 |
aqPlayerState.mDataFormat.mFormatFlags = |
aqPlayerState.mDataFormat.mFormatFlags = |
111 |
kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; |
kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsPacked; |
112 |
|
|
113 |
aqPlayerState.mDataFormat.mBytesPerPacket = uiCoreAudioChannels * 2; |
int samplesize = 4; |
114 |
|
aqPlayerState.mDataFormat.mBytesPerPacket = uiCoreAudioChannels * samplesize; |
115 |
aqPlayerState.mDataFormat.mFramesPerPacket = 1; |
aqPlayerState.mDataFormat.mFramesPerPacket = 1; |
116 |
aqPlayerState.mDataFormat.mBytesPerFrame = uiCoreAudioChannels * 2; |
aqPlayerState.mDataFormat.mBytesPerFrame = uiCoreAudioChannels * samplesize; |
117 |
aqPlayerState.mDataFormat.mChannelsPerFrame = uiCoreAudioChannels; |
aqPlayerState.mDataFormat.mChannelsPerFrame = uiCoreAudioChannels; |
118 |
aqPlayerState.mDataFormat.mBitsPerChannel = 16; |
aqPlayerState.mDataFormat.mBitsPerChannel = 8 * samplesize; |
119 |
|
aqPlayerState.mDataFormat.mReserved = 0; |
120 |
|
|
121 |
aqPlayerState.mBuffers = new AudioQueueBufferRef[uiBufferNumber]; |
aqPlayerState.mBuffers = new AudioQueueBufferRef[uiBufferNumber]; |
122 |
|
|
151 |
CurrentDevice.RemoveListener(this); |
CurrentDevice.RemoveListener(this); |
152 |
} |
} |
153 |
|
|
|
void AudioOutputDeviceCoreAudio::SetAudioDataFormat(AudioStreamBasicDescription* pDataFormat) { |
|
|
pDataFormat->mSampleRate = 44100; |
|
|
pDataFormat->mFormatID = kAudioFormatLinearPCM; |
|
|
|
|
|
pDataFormat->mFormatFlags = |
|
|
kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; |
|
|
|
|
|
pDataFormat->mBytesPerPacket = 4; |
|
|
pDataFormat->mFramesPerPacket = 1; |
|
|
pDataFormat->mBytesPerFrame = 4; |
|
|
pDataFormat->mChannelsPerFrame = 2; |
|
|
pDataFormat->mBitsPerChannel = 16; |
|
|
} |
|
|
|
|
154 |
String AudioOutputDeviceCoreAudio::Name() { |
String AudioOutputDeviceCoreAudio::Name() { |
155 |
return "COREAUDIO"; |
return "COREAUDIO"; |
156 |
} |
} |
160 |
} |
} |
161 |
|
|
162 |
String AudioOutputDeviceCoreAudio::Version() { |
String AudioOutputDeviceCoreAudio::Version() { |
163 |
String s = "$Revision: 1.4 $"; |
String s = "$Revision: 1.5 $"; |
164 |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
165 |
} |
} |
166 |
|
|
211 |
} |
} |
212 |
} |
} |
213 |
|
|
214 |
void AudioOutputDeviceCoreAudio::CreateAndStartAudioQueue() { |
void AudioOutputDeviceCoreAudio::CreateAndStartAudioQueue() throw(Exception) { |
215 |
OSStatus res = AudioQueueNewOutput ( |
OSStatus res = AudioQueueNewOutput ( |
216 |
&aqPlayerState.mDataFormat, |
&aqPlayerState.mDataFormat, |
217 |
HandleOutputBuffer, |
HandleOutputBuffer, |
310 |
* Need to be run from this thread because of CFRunLoopGetCurrent() |
* Need to be run from this thread because of CFRunLoopGetCurrent() |
311 |
* which returns the CFRunLoop object for the current thread. |
* which returns the CFRunLoop object for the current thread. |
312 |
*/ |
*/ |
313 |
CreateAndStartAudioQueue(); |
try { CreateAndStartAudioQueue(); } |
314 |
|
catch(Exception e) { |
315 |
|
std::cerr << "Failed to star audio queue: " + e.Message() << std::endl; |
316 |
|
return 0; |
317 |
|
} |
318 |
} |
} |
319 |
|
|
320 |
destroyMutex.Lock(); |
destroyMutex.Lock(); |
612 |
|
|
613 |
optional<int> |
optional<int> |
614 |
AudioOutputDeviceCoreAudio::ParameterBufferSize::DefaultAsInt(std::map<String,String> Parameters) { |
AudioOutputDeviceCoreAudio::ParameterBufferSize::DefaultAsInt(std::map<String,String> Parameters) { |
615 |
return 128; |
return 256; |
616 |
} |
} |
617 |
|
|
618 |
optional<int> |
optional<int> |