2#include <winpr/stream.h>
4#include <freerdp/codec/audio.h>
5#include <freerdp/codec/dsp.h>
7#define OPUS_TEST_FRAMES 960
11 const AUDIO_FORMAT format = { .wFormatTag = WAVE_FORMAT_OPUS,
13 .nSamplesPerSec = samplesPerSec,
14 .nAvgBytesPerSec = 16000,
16 .wBitsPerSample = 16 };
20static BOOL test_opus_samplerates(
void)
24 FREERDP_DSP_CONTEXT* decoder =
nullptr;
27 if (!freerdp_dsp_supports_format(&valid, FALSE))
29 if (freerdp_dsp_supports_format(&invalid, FALSE))
32 decoder = freerdp_dsp_context_new(FALSE);
35 rc = !freerdp_dsp_context_reset(decoder, &invalid, 0);
39 (void)fprintf(stderr,
"[%s] failed\n", __func__);
40 freerdp_dsp_context_free(decoder);
44static BOOL test_opus_roundtrip(
void)
47 const AUDIO_FORMAT pcm = { .wFormatTag = WAVE_FORMAT_PCM,
49 .nSamplesPerSec = 48000,
50 .nAvgBytesPerSec = 192000,
52 .wBitsPerSample = 16 };
53 INT16 samples[OPUS_TEST_FRAMES * 2] = WINPR_C_ARRAY_INIT;
57 for (
size_t x = 0; x < OPUS_TEST_FRAMES; x++)
59 const INT32 phase = (INT32)(x % 48);
60 const INT16 v = (INT16)(((phase < 24) ? phase : 48 - phase) * 600 - 7200);
62 samples[2 * x + 1] = v;
65 FREERDP_DSP_CONTEXT* encoder = freerdp_dsp_context_new(TRUE);
66 FREERDP_DSP_CONTEXT* decoder = freerdp_dsp_context_new(FALSE);
67 wStream* encoded = Stream_New(
nullptr, 4096);
68 wStream* decoded = Stream_New(
nullptr, 4096);
69 if (!encoder || !decoder || !encoded || !decoded)
73 for (
size_t x = 0; x < 3; x++)
75 if (!freerdp_dsp_context_reset(encoder, &format, OPUS_TEST_FRAMES))
77 if (!freerdp_dsp_context_reset(decoder, &format, 0))
81 if (!freerdp_dsp_encode(encoder, &pcm, (
const BYTE*)samples,
sizeof(samples), encoded))
83 Stream_SealLength(encoded);
84 if (Stream_Length(encoded) == 0)
87 if (!freerdp_dsp_decode(decoder, &format, Stream_Buffer(encoded), Stream_Length(encoded),
90 Stream_SealLength(decoded);
91 rc = (Stream_Length(decoded) ==
sizeof(samples));
95 (void)fprintf(stderr,
"[%s] failed\n", __func__);
96 Stream_Free(encoded, TRUE);
97 Stream_Free(decoded, TRUE);
98 freerdp_dsp_context_free(encoder);
99 freerdp_dsp_context_free(decoder);
105static BOOL test_opus_chunks(
void)
108 const AUDIO_FORMAT pcm = { .wFormatTag = WAVE_FORMAT_PCM,
110 .nSamplesPerSec = 48000,
111 .nAvgBytesPerSec = 192000,
113 .wBitsPerSample = 16 };
114 const size_t chunks[] = { 333, 1000, 2047, 7, 960, 1919, 441, 2880, 100, 3000 };
115 INT16 samples[3000 * 2] = WINPR_C_ARRAY_INIT;
116 size_t in_frames = 0;
117 size_t out_frames = 0;
121 for (
size_t x = 0; x < ARRAYSIZE(samples); x++)
122 samples[x] = (INT16)((x % 96) * 300 - 14400);
124 FREERDP_DSP_CONTEXT* encoder = freerdp_dsp_context_new(TRUE);
125 FREERDP_DSP_CONTEXT* decoder = freerdp_dsp_context_new(FALSE);
126 wStream* encoded = Stream_New(
nullptr, 16);
127 wStream* decoded = Stream_New(
nullptr, 4096);
128 if (!encoder || !decoder || !encoded || !decoded)
130 if (!freerdp_dsp_context_reset(encoder, &format, OPUS_TEST_FRAMES))
132 if (!freerdp_dsp_context_reset(decoder, &format, 0))
135 for (
size_t round = 0; round < 3; round++)
137 for (
size_t x = 0; x < ARRAYSIZE(chunks); x++)
139 Stream_ResetPosition(encoded);
140 Stream_Write_UINT8(encoded, 0x06);
141 if (!freerdp_dsp_encode(encoder, &pcm, (
const BYTE*)samples, chunks[x] * 4, encoded))
143 in_frames += chunks[x];
144 Stream_SealLength(encoded);
145 if (Stream_Length(encoded) <= 1)
148 Stream_ResetPosition(decoded);
149 if (!freerdp_dsp_decode(decoder, &format, Stream_Buffer(encoded) + 1,
150 Stream_Length(encoded) - 1, decoded))
153 const size_t frames = Stream_GetPosition(decoded) / 4;
154 if ((frames != 960) && (frames != 1920) && (frames != 2880))
156 (void)fprintf(stderr,
"[%s] packet of %" PRIuz
" frames\n", __func__, frames);
159 out_frames += frames;
165 rc = (packets > 0) && (out_frames <= in_frames) && (in_frames - out_frames < 2880);
167 (void)fprintf(stderr,
"[%s] %" PRIuz
" frames in, %" PRIuz
" out\n", __func__, in_frames,
172 (void)fprintf(stderr,
"[%s] failed\n", __func__);
173 Stream_Free(encoded, TRUE);
174 Stream_Free(decoded, TRUE);
175 freerdp_dsp_context_free(encoder);
176 freerdp_dsp_context_free(decoder);
180static BOOL test_opus_other_format(
void)
183 const AUDIO_FORMAT pcm = { .wFormatTag = WAVE_FORMAT_PCM,
185 .nSamplesPerSec = 48000,
186 .nAvgBytesPerSec = 192000,
188 .wBitsPerSample = 16 };
189 const BYTE data[4] = WINPR_C_ARRAY_INIT;
192 FREERDP_DSP_CONTEXT* decoder = freerdp_dsp_context_new(FALSE);
193 wStream* decoded = Stream_New(
nullptr, 4096);
194 if (!decoder || !decoded)
198 if (!freerdp_dsp_context_reset(decoder, &opus, 0))
200 if (!freerdp_dsp_context_reset(decoder, &pcm, 0))
202 rc = freerdp_dsp_decode(decoder, &pcm, data,
sizeof(data), decoded);
206 (void)fprintf(stderr,
"[%s] failed\n", __func__);
207 Stream_Free(decoded, TRUE);
208 freerdp_dsp_context_free(decoder);
212int TestFreeRDPCodecDsp(WINPR_ATTR_UNUSED
int argc, WINPR_ATTR_UNUSED
char* argv[])
216 if (!test_opus_samplerates())
218 if (!test_opus_roundtrip())
220 if (!test_opus_chunks())
222 if (!test_opus_other_format())