20 QAudioFormat audioFormat;
22 if ((sf.mFormatFlags & kAudioFormatFlagIsBigEndian) != 0 && QSysInfo::ByteOrder != QSysInfo::LittleEndian)
26 QAudioFormat::SampleFormat format = QAudioFormat::Unknown;
27 switch (sf.mBitsPerChannel) {
29 if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) == 0)
30 format = QAudioFormat::UInt8;
33 if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
34 format = QAudioFormat::Int16;
37 if ((sf.mFormatFlags & kAudioFormatFlagIsSignedInteger) != 0)
38 format = QAudioFormat::Int32;
39 else if ((sf.mFormatFlags & kAudioFormatFlagIsFloat) != 0)
40 format = QAudioFormat::Float;
46 audioFormat.setSampleFormat(format);
47 audioFormat.setSampleRate(sf.mSampleRate);
48 audioFormat.setChannelCount(sf.mChannelsPerFrame);
115 auto channelConfig = format.channelConfig();
116 if (channelConfig == QAudioFormat::ChannelConfigUnknown)
117 channelConfig = QAudioFormat::defaultChannelConfigForChannelCount(format.channelCount());
119 *size =
sizeof(AudioChannelLayout) +
int(QAudioFormat::NChannelPositions)*
sizeof(AudioChannelDescription);
120 auto *layout =
static_cast<AudioChannelLayout *>(malloc(*size));
121 memset(layout, 0, *size);
122 layout->mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelDescriptions;
124 for (
const auto &m : channelMap) {
125 if (channelConfig & QAudioFormat::channelConfig(m.pos))
126 layout->mChannelDescriptions[layout->mNumberChannelDescriptions++].mChannelLabel = m.label;
129 if (channelConfig & QAudioFormat::channelConfig(QAudioFormat::BottomFrontCenter)) {
130 auto &desc = layout->mChannelDescriptions[layout->mNumberChannelDescriptions++];
131 desc.mChannelLabel = kAudioChannelLabel_UseCoordinates;
132 desc.mChannelFlags = kAudioChannelFlags_SphericalCoordinates;
133 desc.mCoordinates[kAudioChannelCoordinates_Azimuth] = 0.f;
134 desc.mCoordinates[kAudioChannelCoordinates_Elevation] = -20.;
135 desc.mCoordinates[kAudioChannelCoordinates_Distance] = 1.f;
137 if (channelConfig & QAudioFormat::channelConfig(QAudioFormat::BottomFrontLeft)) {
138 auto &desc = layout->mChannelDescriptions[layout->mNumberChannelDescriptions++];
139 desc.mChannelLabel = kAudioChannelLabel_UseCoordinates;
140 desc.mChannelFlags = kAudioChannelFlags_SphericalCoordinates;
141 desc.mCoordinates[kAudioChannelCoordinates_Azimuth] = -45.f;
142 desc.mCoordinates[kAudioChannelCoordinates_Elevation] = -20.;
143 desc.mCoordinates[kAudioChannelCoordinates_Distance] = 1.f;
145 if (channelConfig & QAudioFormat::channelConfig(QAudioFormat::BottomFrontRight)) {
146 auto &desc = layout->mChannelDescriptions[layout->mNumberChannelDescriptions++];
147 desc.mChannelLabel = kAudioChannelLabel_UseCoordinates;
148 desc.mChannelFlags = kAudioChannelFlags_SphericalCoordinates;
149 desc.mCoordinates[kAudioChannelCoordinates_Azimuth] = 45.f;
150 desc.mCoordinates[kAudioChannelCoordinates_Elevation] = -20.;
151 desc.mCoordinates[kAudioChannelCoordinates_Distance] = 1.f;
154 return std::unique_ptr<AudioChannelLayout, QFreeDeleter>(layout);
202 for (
const auto &m : layoutTagMap) {
203 if (m.tag == layout->mChannelLayoutTag)
204 return m.channelConfig;
207 quint32 channels = 0;
208 if (layout->mChannelLayoutTag == kAudioChannelLayoutTag_UseChannelDescriptions) {
210 if (layout->mNumberChannelDescriptions == 1
211 && (layout->mChannelDescriptions[0].mChannelLabel == kAudioChannelLabel_Unknown
212 || layout->mChannelDescriptions[0].mChannelLabel == kAudioChannelLabel_Mono))
213 return QAudioFormat::ChannelConfigMono;
214 if (layout->mNumberChannelDescriptions == 2 &&
215 layout->mChannelDescriptions[0].mChannelLabel == kAudioChannelLabel_Unknown &&
216 layout->mChannelDescriptions[1].mChannelLabel == kAudioChannelLabel_Unknown)
217 return QAudioFormat::ChannelConfigStereo;
219 for (uint i = 0; i < layout->mNumberChannelDescriptions; ++i) {
220 const auto channelLabel = layout->mChannelDescriptions[i].mChannelLabel;
221 if (channelLabel == kAudioChannelLabel_Unknown) {
227 const auto found = std::find_if(channelMap, std::end(channelMap),
228 [channelLabel](
const auto &labelWithPos) {
229 return labelWithPos.label == channelLabel;
232 if (found == std::end(channelMap))
233 qWarning() <<
"audio device has unrecognized channel, index:" << i
234 <<
"label:" << channelLabel;
236 channels |= QAudioFormat::channelConfig(found->pos);
239 qWarning() <<
"Channel layout uses unimplemented format, channelLayoutTag:"
240 << layout->mChannelLayoutTag;
242 return QAudioFormat::ChannelConfig(channels);
318 AudioComponentDescription componentDescription;
319 componentDescription.componentType = kAudioUnitType_Output;
320#if defined(Q_OS_MACOS)
321 componentDescription.componentSubType = kAudioUnitSubType_HALOutput;
323 componentDescription.componentSubType = kAudioUnitSubType_RemoteIO;
325 componentDescription.componentManufacturer = kAudioUnitManufacturer_Apple;
326 componentDescription.componentFlags = 0;
327 componentDescription.componentFlagsMask = 0;
329 AudioComponent component = AudioComponentFindNext(
nullptr, &componentDescription);
330 if (component ==
nullptr) {
331 qWarning() <<
"makeAudioUnitForIO: Failed to find Output component";
336 if (AudioComponentInstanceNew(component, &audioUnit) != noErr) {
337 qWarning() <<
"makeAudioUnitForIO: Unable to Open Output Component";
383 const AudioStreamBasicDescription &format)
385 OSStatus status = AudioUnitSetProperty(audioUnit.get(), kAudioUnitProperty_StreamFormat,
386 kAudioUnitScope_Input, element, &format,
sizeof(format));
387 if (status != noErr) {
388 qWarning() <<
"AudioUnit: Unable to set stream format" << status;
395 const AudioStreamBasicDescription &format)
397 if (AudioUnitSetProperty(audioUnit.get(), kAudioUnitProperty_StreamFormat,
398 kAudioUnitScope_Output, element, &format,
sizeof(format))
400 qWarning() <<
"AudioUnit: Unable to set stream format";
505 OSStatus status = AudioUnitSetProperty(audioUnit.get(), kAudioUnitProperty_SetRenderCallback,
506 kAudioUnitScope_Global, 0, &callback,
sizeof(callback));
508 if (status != noErr) {
509 qWarning() <<
"AudioUnitSetProperty: Failed to set AudioUnit "
510 "kAudioUnitProperty_SetRenderCallback"
531 AudioUnitElement element)
533 AudioStreamBasicDescription ret;
534 UInt32 size =
sizeof(AudioStreamBasicDescription);
536 if (AudioUnitGetProperty(audioUnit.get(), kAudioUnitProperty_StreamFormat,
537 kAudioUnitScope_Input, element, &ret, &size)
539 qWarning() <<
"QAudioSource: Unable to retrieve device format";