1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qpulsehelpers_p.h"
5
6QT_BEGIN_NAMESPACE
7
8Q_LOGGING_CATEGORY(qLcPulseAudioOut, "qt.multimedia.pulseaudio.output")
9
10namespace QPulseAudioInternal
11{
12pa_sample_spec audioFormatToSampleSpec(const QAudioFormat &format)
13{
14 pa_sample_spec spec;
15
16 spec.rate = format.sampleRate();
17 spec.channels = format.channelCount();
18 spec.format = PA_SAMPLE_INVALID;
19 const bool isBigEndian = QSysInfo::ByteOrder == QSysInfo::BigEndian;
20
21 if (format.sampleFormat() == QAudioFormat::UInt8) {
22 spec.format = PA_SAMPLE_U8;
23 } else if (format.sampleFormat() == QAudioFormat::Int16) {
24 spec.format = isBigEndian ? PA_SAMPLE_S16BE : PA_SAMPLE_S16LE;
25 } else if (format.sampleFormat() == QAudioFormat::Int32) {
26 spec.format = isBigEndian ? PA_SAMPLE_S32BE : PA_SAMPLE_S32LE;
27 } else if (format.sampleFormat() == QAudioFormat::Float) {
28 spec.format = isBigEndian ? PA_SAMPLE_FLOAT32BE : PA_SAMPLE_FLOAT32LE;
29 }
30
31 return spec;
32}
33
34pa_channel_map channelMapForAudioFormat(const QAudioFormat &format)
35{
36 pa_channel_map map;
37 map.channels = 0;
38
39 auto config = format.channelConfig();
40 if (config == QAudioFormat::ChannelConfigUnknown)
41 config = QAudioFormat::defaultChannelConfigForChannelCount(channelCount: format.channelCount());
42
43 if (config == QAudioFormat::ChannelConfigMono) {
44 map.channels = 1;
45 map.map[0] = PA_CHANNEL_POSITION_MONO;
46 } else {
47 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::FrontLeft))
48 map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_LEFT;
49 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::FrontRight))
50 map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT;
51 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::FrontCenter))
52 map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_CENTER;
53 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::LFE))
54 map.map[map.channels++] = PA_CHANNEL_POSITION_LFE;
55 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::BackLeft))
56 map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_LEFT;
57 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::BackRight))
58 map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_RIGHT;
59 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::FrontLeftOfCenter))
60 map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
61 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::FrontRightOfCenter))
62 map.map[map.channels++] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
63 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::BackCenter))
64 map.map[map.channels++] = PA_CHANNEL_POSITION_REAR_CENTER;
65 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::LFE2))
66 map.map[map.channels++] = PA_CHANNEL_POSITION_LFE;
67 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::SideLeft))
68 map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_LEFT;
69 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::SideRight))
70 map.map[map.channels++] = PA_CHANNEL_POSITION_SIDE_RIGHT;
71 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::TopFrontLeft))
72 map.map[map.channels++] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
73 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::TopFrontRight))
74 map.map[map.channels++] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
75 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::TopFrontCenter))
76 map.map[map.channels++] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
77 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::TopCenter))
78 map.map[map.channels++] = PA_CHANNEL_POSITION_TOP_CENTER;
79 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::TopBackLeft))
80 map.map[map.channels++] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
81 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::TopBackRight))
82 map.map[map.channels++] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
83 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::TopSideLeft))
84 map.map[map.channels++] = PA_CHANNEL_POSITION_AUX0;
85 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::TopSideRight))
86 map.map[map.channels++] = PA_CHANNEL_POSITION_AUX1;
87 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::TopBackCenter))
88 map.map[map.channels++] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
89 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::BottomFrontCenter))
90 map.map[map.channels++] = PA_CHANNEL_POSITION_AUX2;
91 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::BottomFrontLeft))
92 map.map[map.channels++] = PA_CHANNEL_POSITION_AUX3;
93 if (config & QAudioFormat::channelConfig(channels: QAudioFormat::BottomFrontRight))
94 map.map[map.channels++] = PA_CHANNEL_POSITION_AUX4;
95 }
96
97 Q_ASSERT(qPopulationCount(config) == map.channels);
98 return map;
99}
100
101QAudioFormat::ChannelConfig channelConfigFromMap(const pa_channel_map &map)
102{
103 quint32 config = 0;
104 for (int i = 0; i < map.channels; ++i) {
105 switch (map.map[i]) {
106 case PA_CHANNEL_POSITION_MONO:
107 case PA_CHANNEL_POSITION_FRONT_CENTER:
108 config |= QAudioFormat::channelConfig(channels: QAudioFormat::FrontCenter);
109 break;
110 case PA_CHANNEL_POSITION_FRONT_LEFT:
111 config |= QAudioFormat::channelConfig(channels: QAudioFormat::FrontLeft);
112 break;
113 case PA_CHANNEL_POSITION_FRONT_RIGHT:
114 config |= QAudioFormat::channelConfig(channels: QAudioFormat::FrontRight);
115 break;
116 case PA_CHANNEL_POSITION_REAR_CENTER:
117 config |= QAudioFormat::channelConfig(channels: QAudioFormat::BackCenter);
118 break;
119 case PA_CHANNEL_POSITION_REAR_LEFT:
120 config |= QAudioFormat::channelConfig(channels: QAudioFormat::BackLeft);
121 break;
122 case PA_CHANNEL_POSITION_REAR_RIGHT:
123 config |= QAudioFormat::channelConfig(channels: QAudioFormat::BackRight);
124 break;
125 case PA_CHANNEL_POSITION_LFE:
126 config |= QAudioFormat::channelConfig(channels: QAudioFormat::LFE);
127 break;
128 case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
129 config |= QAudioFormat::channelConfig(channels: QAudioFormat::FrontLeftOfCenter);
130 break;
131 case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
132 config |= QAudioFormat::channelConfig(channels: QAudioFormat::FrontRightOfCenter);
133 break;
134 case PA_CHANNEL_POSITION_SIDE_LEFT:
135 config |= QAudioFormat::channelConfig(channels: QAudioFormat::SideLeft);
136 break;
137 case PA_CHANNEL_POSITION_SIDE_RIGHT:
138 config |= QAudioFormat::channelConfig(channels: QAudioFormat::SideRight);
139 break;
140
141 case PA_CHANNEL_POSITION_TOP_CENTER:
142 config |= QAudioFormat::channelConfig(channels: QAudioFormat::TopCenter);
143 break;
144 case PA_CHANNEL_POSITION_TOP_FRONT_LEFT:
145 config |= QAudioFormat::channelConfig(channels: QAudioFormat::TopFrontLeft);
146 break;
147 case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT:
148 config |= QAudioFormat::channelConfig(channels: QAudioFormat::TopFrontRight);
149 break;
150 case PA_CHANNEL_POSITION_TOP_FRONT_CENTER:
151 config |= QAudioFormat::channelConfig(channels: QAudioFormat::TopFrontCenter);
152 break;
153 case PA_CHANNEL_POSITION_TOP_REAR_LEFT:
154 config |= QAudioFormat::channelConfig(channels: QAudioFormat::TopBackLeft);
155 break;
156 case PA_CHANNEL_POSITION_TOP_REAR_RIGHT:
157 config |= QAudioFormat::channelConfig(channels: QAudioFormat::TopBackRight);
158 break;
159 case PA_CHANNEL_POSITION_TOP_REAR_CENTER:
160 config |= QAudioFormat::channelConfig(channels: QAudioFormat::TopBackCenter);
161 break;
162 default:
163 break;
164 }
165 }
166 return QAudioFormat::ChannelConfig(config);
167}
168
169QAudioFormat sampleSpecToAudioFormat(const pa_sample_spec &spec)
170{
171 QAudioFormat format;
172
173 format.setSampleRate(spec.rate);
174 format.setChannelCount(spec.channels);
175 QAudioFormat::SampleFormat sampleFormat;
176 switch (spec.format) {
177 case PA_SAMPLE_U8:
178 sampleFormat = QAudioFormat::UInt8;
179 break;
180 case PA_SAMPLE_S16LE:
181 case PA_SAMPLE_S16BE:
182 sampleFormat = QAudioFormat::Int16;
183 break;
184 case PA_SAMPLE_FLOAT32LE:
185 case PA_SAMPLE_FLOAT32BE:
186 sampleFormat = QAudioFormat::Float;
187 break;
188 case PA_SAMPLE_S32LE:
189 case PA_SAMPLE_S32BE:
190 sampleFormat = QAudioFormat::Int32;
191 break;
192 default:
193 return {};
194 }
195
196 format.setSampleFormat(sampleFormat);
197 return format;
198}
199
200}
201
202QT_END_NAMESPACE
203

source code of qtmultimedia/src/multimedia/pulseaudio/qpulsehelpers.cpp