Coverage Report

Created: 2024-05-20 06:11

/src/FreeRDP/libfreerdp/codec/audio.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * FreeRDP: A Remote Desktop Protocol Implementation
3
 * Audio Formats
4
 *
5
 * Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6
 *
7
 * Licensed under the Apache License, Version 2.0 (the "License");
8
 * you may not use this file except in compliance with the License.
9
 * You may obtain a copy of the License at
10
 *
11
 *     http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 * Unless required by applicable law or agreed to in writing, software
14
 * distributed under the License is distributed on an "AS IS" BASIS,
15
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 * See the License for the specific language governing permissions and
17
 * limitations under the License.
18
 */
19
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
0
{
31
0
  UINT32 mstime = 0;
32
0
  UINT32 wSamples = 0;
33
34
  /**
35
   * [MSDN-AUDIOFORMAT]:
36
   * http://msdn.microsoft.com/en-us/library/ms713497.aspx
37
   */
38
39
0
  if (format->wBitsPerSample)
40
0
  {
41
0
    const size_t samples = (size * 8) / format->wBitsPerSample;
42
0
    WINPR_ASSERT(samples <= UINT32_MAX);
43
0
    wSamples = (UINT32)samples;
44
0
    mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
45
0
  }
46
0
  else
47
0
  {
48
0
    mstime = 0;
49
50
0
    if (format->wFormatTag == WAVE_FORMAT_GSM610)
51
0
    {
52
0
      UINT16 nSamplesPerBlock = 0;
53
54
0
      if ((format->cbSize == 2) && (format->data))
55
0
      {
56
0
        nSamplesPerBlock = *((UINT16*)format->data);
57
0
        const size_t samples = (size / format->nBlockAlign) * nSamplesPerBlock;
58
0
        WINPR_ASSERT(samples <= UINT32_MAX);
59
0
        wSamples = (UINT32)samples;
60
0
        mstime = (((wSamples * 1000) / format->nSamplesPerSec) / format->nChannels);
61
0
      }
62
0
      else
63
0
      {
64
0
        WLog_ERR(TAG,
65
0
                 "audio_format_compute_time_length: invalid WAVE_FORMAT_GSM610 format");
66
0
      }
67
0
    }
68
0
    else
69
0
    {
70
0
      WLog_ERR(TAG, "audio_format_compute_time_length: unknown format %" PRIu16 "",
71
0
               format->wFormatTag);
72
0
    }
73
0
  }
74
75
0
  return mstime;
76
0
}
77
78
char* audio_format_get_tag_string(UINT16 wFormatTag)
79
0
{
80
0
  switch (wFormatTag)
81
0
  {
82
0
    case WAVE_FORMAT_PCM:
83
0
      return "WAVE_FORMAT_PCM";
84
85
0
    case WAVE_FORMAT_ADPCM:
86
0
      return "WAVE_FORMAT_ADPCM";
87
88
0
    case WAVE_FORMAT_ALAW:
89
0
      return "WAVE_FORMAT_ALAW";
90
91
0
    case WAVE_FORMAT_MULAW:
92
0
      return "WAVE_FORMAT_MULAW";
93
94
0
    case WAVE_FORMAT_DVI_ADPCM:
95
0
      return "WAVE_FORMAT_DVI_ADPCM";
96
97
0
    case WAVE_FORMAT_GSM610:
98
0
      return "WAVE_FORMAT_GSM610";
99
100
0
    case WAVE_FORMAT_MSG723:
101
0
      return "WAVE_FORMAT_MSG723";
102
103
0
    case WAVE_FORMAT_DSPGROUP_TRUESPEECH:
104
0
      return "WAVE_FORMAT_DSPGROUP_TRUESPEECH ";
105
106
0
    case WAVE_FORMAT_MPEGLAYER3:
107
0
      return "WAVE_FORMAT_MPEGLAYER3";
108
109
0
    case WAVE_FORMAT_WMAUDIO2:
110
0
      return "WAVE_FORMAT_WMAUDIO2";
111
112
0
    case WAVE_FORMAT_AAC_MS:
113
0
      return "WAVE_FORMAT_AAC_MS";
114
0
  }
115
116
0
  return "WAVE_FORMAT_UNKNOWN";
117
0
}
118
119
void audio_format_print(wLog* log, DWORD level, const AUDIO_FORMAT* format)
120
0
{
121
0
  WLog_Print(log, level,
122
0
             "%s:\t wFormatTag: 0x%04" PRIX16 " nChannels: %" PRIu16 " nSamplesPerSec: %" PRIu32
123
0
             " "
124
0
             "nAvgBytesPerSec: %" PRIu32 " nBlockAlign: %" PRIu16 " wBitsPerSample: %" PRIu16
125
0
             " cbSize: %" PRIu16 "",
126
0
             audio_format_get_tag_string(format->wFormatTag), format->wFormatTag,
127
0
             format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec,
128
0
             format->nBlockAlign, format->wBitsPerSample, format->cbSize);
129
0
}
130
131
void audio_formats_print(wLog* log, DWORD level, const AUDIO_FORMAT* formats, UINT16 count)
132
0
{
133
0
  if (formats)
134
0
  {
135
0
    WLog_Print(log, level, "AUDIO_FORMATS (%" PRIu16 ") ={", count);
136
137
0
    for (UINT32 index = 0; index < count; index++)
138
0
    {
139
0
      const AUDIO_FORMAT* format = &formats[index];
140
0
      WLog_Print(log, level, "\t");
141
0
      audio_format_print(log, level, format);
142
0
    }
143
144
0
    WLog_Print(log, level, "}");
145
0
  }
146
0
}
147
148
BOOL audio_format_read(wStream* s, AUDIO_FORMAT* format)
149
0
{
150
0
  if (!s || !format)
151
0
    return FALSE;
152
153
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, 18))
154
0
    return FALSE;
155
156
0
  Stream_Read_UINT16(s, format->wFormatTag);
157
0
  Stream_Read_UINT16(s, format->nChannels);
158
0
  Stream_Read_UINT32(s, format->nSamplesPerSec);
159
0
  Stream_Read_UINT32(s, format->nAvgBytesPerSec);
160
0
  Stream_Read_UINT16(s, format->nBlockAlign);
161
0
  Stream_Read_UINT16(s, format->wBitsPerSample);
162
0
  Stream_Read_UINT16(s, format->cbSize);
163
164
0
  if (!Stream_CheckAndLogRequiredLength(TAG, s, format->cbSize))
165
0
    return FALSE;
166
167
0
  format->data = NULL;
168
169
0
  if (format->cbSize > 0)
170
0
  {
171
0
    format->data = malloc(format->cbSize);
172
173
0
    if (!format->data)
174
0
      return FALSE;
175
176
0
    Stream_Read(s, format->data, format->cbSize);
177
0
  }
178
179
0
  return TRUE;
180
0
}
181
182
BOOL audio_format_write(wStream* s, const AUDIO_FORMAT* format)
183
0
{
184
0
  if (!s || !format)
185
0
    return FALSE;
186
187
0
  if (!Stream_EnsureRemainingCapacity(s, 18 + format->cbSize))
188
0
    return FALSE;
189
190
0
  Stream_Write_UINT16(s, format->wFormatTag);      /* wFormatTag (WAVE_FORMAT_PCM) */
191
0
  Stream_Write_UINT16(s, format->nChannels);       /* nChannels */
192
0
  Stream_Write_UINT32(s, format->nSamplesPerSec);  /* nSamplesPerSec */
193
0
  Stream_Write_UINT32(s, format->nAvgBytesPerSec); /* nAvgBytesPerSec */
194
0
  Stream_Write_UINT16(s, format->nBlockAlign);     /* nBlockAlign */
195
0
  Stream_Write_UINT16(s, format->wBitsPerSample);  /* wBitsPerSample */
196
0
  Stream_Write_UINT16(s, format->cbSize);          /* cbSize */
197
198
0
  if (format->cbSize > 0)
199
0
    Stream_Write(s, format->data, format->cbSize);
200
201
0
  return TRUE;
202
0
}
203
204
BOOL audio_format_copy(const AUDIO_FORMAT* srcFormat, AUDIO_FORMAT* dstFormat)
205
0
{
206
0
  if (!srcFormat || !dstFormat)
207
0
    return FALSE;
208
209
0
  *dstFormat = *srcFormat;
210
211
0
  if (srcFormat->cbSize > 0)
212
0
  {
213
0
    dstFormat->data = malloc(srcFormat->cbSize);
214
215
0
    if (!dstFormat->data)
216
0
      return FALSE;
217
218
0
    memcpy(dstFormat->data, srcFormat->data, dstFormat->cbSize);
219
0
  }
220
221
0
  return TRUE;
222
0
}
223
224
BOOL audio_format_compatible(const AUDIO_FORMAT* with, const AUDIO_FORMAT* what)
225
0
{
226
0
  if (!with || !what)
227
0
    return FALSE;
228
229
0
  if (with->wFormatTag != WAVE_FORMAT_UNKNOWN)
230
0
  {
231
0
    if (with->wFormatTag != what->wFormatTag)
232
0
      return FALSE;
233
0
  }
234
235
0
  if (with->nChannels != 0)
236
0
  {
237
0
    if (with->nChannels != what->nChannels)
238
0
      return FALSE;
239
0
  }
240
241
0
  if (with->nSamplesPerSec != 0)
242
0
  {
243
0
    if (with->nSamplesPerSec != what->nSamplesPerSec)
244
0
      return FALSE;
245
0
  }
246
247
0
  if (with->wBitsPerSample != 0)
248
0
  {
249
0
    if (with->wBitsPerSample != what->wBitsPerSample)
250
0
      return FALSE;
251
0
  }
252
253
0
  return TRUE;
254
0
}
255
256
static BOOL audio_format_valid(const AUDIO_FORMAT* format)
257
0
{
258
0
  if (!format)
259
0
    return FALSE;
260
0
261
0
  if (format->nChannels == 0)
262
0
    return FALSE;
263
0
264
0
  if (format->nSamplesPerSec == 0)
265
0
    return FALSE;
266
0
267
0
  return TRUE;
268
0
}
269
270
AUDIO_FORMAT* audio_format_new(void)
271
0
{
272
0
  return audio_formats_new(1);
273
0
}
274
275
AUDIO_FORMAT* audio_formats_new(size_t count)
276
0
{
277
0
  return calloc(count, sizeof(AUDIO_FORMAT));
278
0
}
279
280
void audio_format_free(AUDIO_FORMAT* format)
281
0
{
282
0
  if (format)
283
0
    free(format->data);
284
0
}
285
286
void audio_formats_free(AUDIO_FORMAT* formats, size_t count)
287
0
{
288
0
  if (formats)
289
0
  {
290
0
    for (size_t index = 0; index < count; index++)
291
0
    {
292
0
      AUDIO_FORMAT* format = &formats[index];
293
0
      audio_format_free(format);
294
0
    }
295
296
0
    free(formats);
297
0
  }
298
0
}