FreeRDP
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 
29 UINT32 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 = *((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 
78 const 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  default:
115  return "WAVE_FORMAT_UNKNOWN";
116  }
117 }
118 
119 void audio_format_print(wLog* log, DWORD level, const AUDIO_FORMAT* format)
120 {
121  WLog_Print(log, level,
122  "%s:\t wFormatTag: 0x%04" PRIX16 " nChannels: %" PRIu16 " nSamplesPerSec: %" PRIu32
123  " "
124  "nAvgBytesPerSec: %" PRIu32 " nBlockAlign: %" PRIu16 " wBitsPerSample: %" PRIu16
125  " cbSize: %" PRIu16 "",
126  audio_format_get_tag_string(format->wFormatTag), format->wFormatTag,
127  format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec,
128  format->nBlockAlign, format->wBitsPerSample, format->cbSize);
129 }
130 
131 void audio_formats_print(wLog* log, DWORD level, const AUDIO_FORMAT* formats, UINT16 count)
132 {
133  if (formats)
134  {
135  WLog_Print(log, level, "AUDIO_FORMATS (%" PRIu16 ") ={", count);
136 
137  for (UINT32 index = 0; index < count; index++)
138  {
139  const AUDIO_FORMAT* format = &formats[index];
140  WLog_Print(log, level, "\t");
141  audio_format_print(log, level, format);
142  }
143 
144  WLog_Print(log, level, "}");
145  }
146 }
147 
148 BOOL audio_format_read(wStream* s, AUDIO_FORMAT* format)
149 {
150  if (!s || !format)
151  return FALSE;
152 
153  if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
154  return FALSE;
155 
156  Stream_Read_UINT16(s, format->wFormatTag);
157  Stream_Read_UINT16(s, format->nChannels);
158  Stream_Read_UINT32(s, format->nSamplesPerSec);
159  Stream_Read_UINT32(s, format->nAvgBytesPerSec);
160  Stream_Read_UINT16(s, format->nBlockAlign);
161  Stream_Read_UINT16(s, format->wBitsPerSample);
162  Stream_Read_UINT16(s, format->cbSize);
163 
164  if (!Stream_CheckAndLogRequiredLength(TAG, s, format->cbSize))
165  return FALSE;
166 
167  format->data = NULL;
168 
169  if (format->cbSize > 0)
170  {
171  format->data = malloc(format->cbSize);
172 
173  if (!format->data)
174  return FALSE;
175 
176  Stream_Read(s, format->data, format->cbSize);
177  }
178 
179  return TRUE;
180 }
181 
182 BOOL audio_format_write(wStream* s, const AUDIO_FORMAT* format)
183 {
184  if (!s || !format)
185  return FALSE;
186 
187  if (!Stream_EnsureRemainingCapacity(s, 18 + format->cbSize))
188  return FALSE;
189 
190  Stream_Write_UINT16(s, format->wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */
191  Stream_Write_UINT16(s, format->nChannels); /* nChannels */
192  Stream_Write_UINT32(s, format->nSamplesPerSec); /* nSamplesPerSec */
193  Stream_Write_UINT32(s, format->nAvgBytesPerSec); /* nAvgBytesPerSec */
194  Stream_Write_UINT16(s, format->nBlockAlign); /* nBlockAlign */
195  Stream_Write_UINT16(s, format->wBitsPerSample); /* wBitsPerSample */
196  Stream_Write_UINT16(s, format->cbSize); /* cbSize */
197 
198  if (format->cbSize > 0)
199  Stream_Write(s, format->data, format->cbSize);
200 
201  return TRUE;
202 }
203 
204 BOOL audio_format_copy(const AUDIO_FORMAT* WINPR_RESTRICT srcFormat,
205  AUDIO_FORMAT* WINPR_RESTRICT dstFormat)
206 {
207  if (!srcFormat || !dstFormat)
208  return FALSE;
209 
210  *dstFormat = *srcFormat;
211 
212  if (srcFormat->cbSize > 0)
213  {
214  dstFormat->data = malloc(srcFormat->cbSize);
215 
216  if (!dstFormat->data)
217  return FALSE;
218 
219  memcpy(dstFormat->data, srcFormat->data, dstFormat->cbSize);
220  }
221 
222  return TRUE;
223 }
224 
225 BOOL audio_format_compatible(const AUDIO_FORMAT* with, const AUDIO_FORMAT* what)
226 {
227  if (!with || !what)
228  return FALSE;
229 
230  if (with->wFormatTag != WAVE_FORMAT_UNKNOWN)
231  {
232  if (with->wFormatTag != what->wFormatTag)
233  return FALSE;
234  }
235 
236  if (with->nChannels != 0)
237  {
238  if (with->nChannels != what->nChannels)
239  return FALSE;
240  }
241 
242  if (with->nSamplesPerSec != 0)
243  {
244  if (with->nSamplesPerSec != what->nSamplesPerSec)
245  return FALSE;
246  }
247 
248  if (with->wBitsPerSample != 0)
249  {
250  if (with->wBitsPerSample != what->wBitsPerSample)
251  return FALSE;
252  }
253 
254  return TRUE;
255 }
256 
257 static BOOL audio_format_valid(const AUDIO_FORMAT* format)
258 {
259  if (!format)
260  return FALSE;
261 
262  if (format->nChannels == 0)
263  return FALSE;
264 
265  if (format->nSamplesPerSec == 0)
266  return FALSE;
267 
268  return TRUE;
269 }
270 
271 AUDIO_FORMAT* audio_format_new(void)
272 {
273  return audio_formats_new(1);
274 }
275 
276 AUDIO_FORMAT* audio_formats_new(size_t count)
277 {
278  return calloc(count, sizeof(AUDIO_FORMAT));
279 }
280 
281 void audio_format_free(AUDIO_FORMAT* format)
282 {
283  if (format)
284  free(format->data);
285 }
286 
287 void audio_formats_free(AUDIO_FORMAT* formats, size_t count)
288 {
289  if (formats)
290  {
291  for (size_t index = 0; index < count; index++)
292  {
293  AUDIO_FORMAT* format = &formats[index];
294  audio_format_free(format);
295  }
296 
297  free(formats);
298  }
299 }