FreeRDP
Loading...
Searching...
No Matches
audio.c
1
20#include <freerdp/config.h>
21
22#include <winpr/crt.h>
23
24#include <freerdp/log.h>
25#include <freerdp/codec/audio.h>
26
27#define TAG FREERDP_TAG("codec")
28
29UINT32 audio_format_compute_time_length(const AUDIO_FORMAT* format, size_t size)
30{
31 UINT32 mstime = 0;
32 UINT32 wSamples = 0;
33
39 if (format->wBitsPerSample)
40 {
41 const size_t samples = (size * 8) / format->wBitsPerSample;
42 WINPR_ASSERT(samples <= UINT32_MAX);
43 wSamples = (UINT32)samples;
44 mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
45 }
46 else
47 {
48 mstime = 0;
49
50 if (format->wFormatTag == WAVE_FORMAT_GSM610)
51 {
52 UINT16 nSamplesPerBlock = 0;
53
54 if ((format->cbSize == 2) && (format->data))
55 {
56 nSamplesPerBlock = *(WINPR_PACKED_ALIGN_CAST(UINT16*, format->data));
57 const size_t samples = (size / format->nBlockAlign) * nSamplesPerBlock;
58 WINPR_ASSERT(samples <= UINT32_MAX);
59 wSamples = (UINT32)samples;
60 mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
61 }
62 else
63 {
64 WLog_ERR(TAG,
65 "audio_format_compute_time_length: invalid WAVE_FORMAT_GSM610 format");
66 }
67 }
68 else
69 {
70 WLog_ERR(TAG, "audio_format_compute_time_length: unknown format %" PRIu16 "",
71 format->wFormatTag);
72 }
73 }
74
75 return mstime;
76}
77
78const char* audio_format_get_tag_string(UINT16 wFormatTag)
79{
80 switch (wFormatTag)
81 {
82 case WAVE_FORMAT_PCM:
83 return "WAVE_FORMAT_PCM";
84
85 case WAVE_FORMAT_ADPCM:
86 return "WAVE_FORMAT_ADPCM";
87
88 case WAVE_FORMAT_ALAW:
89 return "WAVE_FORMAT_ALAW";
90
91 case WAVE_FORMAT_MULAW:
92 return "WAVE_FORMAT_MULAW";
93
94 case WAVE_FORMAT_DVI_ADPCM:
95 return "WAVE_FORMAT_DVI_ADPCM";
96
97 case WAVE_FORMAT_GSM610:
98 return "WAVE_FORMAT_GSM610";
99
100 case WAVE_FORMAT_MSG723:
101 return "WAVE_FORMAT_MSG723";
102
103 case WAVE_FORMAT_DSPGROUP_TRUESPEECH:
104 return "WAVE_FORMAT_DSPGROUP_TRUESPEECH";
105
106 case WAVE_FORMAT_MPEGLAYER3:
107 return "WAVE_FORMAT_MPEGLAYER3";
108
109 case WAVE_FORMAT_WMAUDIO2:
110 return "WAVE_FORMAT_WMAUDIO2";
111
112 case WAVE_FORMAT_AAC_MS:
113 return "WAVE_FORMAT_AAC_MS";
114
115 case WAVE_FORMAT_OPUS:
116 return "WAVE_FORMAT_OPUS";
117
118 default:
119 return "WAVE_FORMAT_UNKNOWN";
120 }
121}
122
123void audio_format_print(wLog* log, DWORD level, const AUDIO_FORMAT* format)
124{
125 WLog_Print(log, level,
126 "%s:\t wFormatTag: 0x%04" PRIX16 " nChannels: %" PRIu16 " nSamplesPerSec: %" PRIu32
127 " "
128 "nAvgBytesPerSec: %" PRIu32 " nBlockAlign: %" PRIu16 " wBitsPerSample: %" PRIu16
129 " cbSize: %" PRIu16 "",
130 audio_format_get_tag_string(format->wFormatTag), format->wFormatTag,
131 format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec,
132 format->nBlockAlign, format->wBitsPerSample, format->cbSize);
133}
134
135void audio_formats_print(wLog* log, DWORD level, const AUDIO_FORMAT* formats, UINT16 count)
136{
137 if (formats)
138 {
139 WLog_Print(log, level, "AUDIO_FORMATS (%" PRIu16 ") ={", count);
140
141 for (UINT32 index = 0; index < count; index++)
142 {
143 const AUDIO_FORMAT* format = &formats[index];
144 WLog_Print(log, level, "\t");
145 audio_format_print(log, level, format);
146 }
147
148 WLog_Print(log, level, "}");
149 }
150}
151
152BOOL audio_format_read(wStream* s, AUDIO_FORMAT* format)
153{
154 if (!s || !format)
155 return FALSE;
156
157 if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
158 return FALSE;
159
160 Stream_Read_UINT16(s, format->wFormatTag);
161 Stream_Read_UINT16(s, format->nChannels);
162 Stream_Read_UINT32(s, format->nSamplesPerSec);
163 Stream_Read_UINT32(s, format->nAvgBytesPerSec);
164 Stream_Read_UINT16(s, format->nBlockAlign);
165 Stream_Read_UINT16(s, format->wBitsPerSample);
166 Stream_Read_UINT16(s, format->cbSize);
167
168 if (!Stream_CheckAndLogRequiredLength(TAG, s, format->cbSize))
169 return FALSE;
170
171 format->data = nullptr;
172
173 if (format->cbSize > 0)
174 {
175 format->data = malloc(format->cbSize);
176
177 if (!format->data)
178 return FALSE;
179
180 Stream_Read(s, format->data, format->cbSize);
181 }
182
183 return TRUE;
184}
185
186BOOL audio_format_write(wStream* s, const AUDIO_FORMAT* format)
187{
188 if (!s || !format)
189 return FALSE;
190
191 if (!Stream_EnsureRemainingCapacity(s, 18ull + format->cbSize))
192 return FALSE;
193
194 Stream_Write_UINT16(s, format->wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */
195 Stream_Write_UINT16(s, format->nChannels); /* nChannels */
196 Stream_Write_UINT32(s, format->nSamplesPerSec); /* nSamplesPerSec */
197 Stream_Write_UINT32(s, format->nAvgBytesPerSec); /* nAvgBytesPerSec */
198 Stream_Write_UINT16(s, format->nBlockAlign); /* nBlockAlign */
199 Stream_Write_UINT16(s, format->wBitsPerSample); /* wBitsPerSample */
200 Stream_Write_UINT16(s, format->cbSize); /* cbSize */
201
202 if (format->cbSize > 0)
203 Stream_Write(s, format->data, format->cbSize);
204
205 return TRUE;
206}
207
208BOOL audio_format_copy(const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
209 AUDIO_FORMAT* WINPR_RESTRICT dstFormat)
210{
211 if (!srcFormat || !dstFormat)
212 return FALSE;
213
214 *dstFormat = *srcFormat;
215
216 if (srcFormat->cbSize > 0)
217 {
218 dstFormat->data = malloc(srcFormat->cbSize);
219
220 if (!dstFormat->data)
221 return FALSE;
222
223 memcpy(dstFormat->data, srcFormat->data, dstFormat->cbSize);
224 }
225
226 return TRUE;
227}
228
229BOOL audio_format_compatible(const AUDIO_FORMAT* with, const AUDIO_FORMAT* what)
230{
231 if (!with || !what)
232 return FALSE;
233
234 if (with->wFormatTag != WAVE_FORMAT_UNKNOWN)
235 {
236 if (with->wFormatTag != what->wFormatTag)
237 return FALSE;
238 }
239
240 if (with->nChannels != 0)
241 {
242 if (with->nChannels != what->nChannels)
243 return FALSE;
244 }
245
246 if (with->nSamplesPerSec != 0)
247 {
248 if (with->nSamplesPerSec != what->nSamplesPerSec)
249 return FALSE;
250 }
251
252 if (with->wBitsPerSample != 0)
253 {
254 if (with->wBitsPerSample != what->wBitsPerSample)
255 return FALSE;
256 }
257
258 return TRUE;
259}
260
261AUDIO_FORMAT* audio_format_new(void)
262{
263 return audio_formats_new(1);
264}
265
266AUDIO_FORMAT* audio_formats_new(size_t count)
267{
268 return calloc(count, sizeof(AUDIO_FORMAT));
269}
270
271void audio_format_free(AUDIO_FORMAT* format)
272{
273 if (format)
274 free(format->data);
275}
276
277void audio_formats_free(AUDIO_FORMAT* formats, size_t count)
278{
279 if (formats)
280 {
281 for (size_t index = 0; index < count; index++)
282 {
283 AUDIO_FORMAT* format = &formats[index];
284 audio_format_free(format);
285 }
286
287 free(formats);
288 }
289}