You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

226 lines
8.0 KiB

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "opus_codec.h"
#define SAMPLE_RATE 48000
#define CHANNELS 1
#define FRAME_MS 20
#define FRAME_SAMPLES (SAMPLE_RATE * FRAME_MS / 1000) /* 960 */
static int test_encode_decode_silence(void) {
printf("test_encode_decode_silence: ");
opus_codec_encoder_t* enc = opus_codec_encoder_create(SAMPLE_RATE, CHANNELS);
if (!enc) { printf("FAIL (encoder_create)\n"); return 1; }
opus_codec_decoder_t* dec = opus_codec_decoder_create(SAMPLE_RATE, CHANNELS);
if (!dec) { printf("FAIL (decoder_create)\n"); opus_codec_encoder_destroy(enc); return 1; }
int16_t pcm_in[FRAME_SAMPLES];
memset(pcm_in, 0, sizeof(pcm_in));
uint8_t packet[4000];
int packet_len = opus_codec_encode(enc, pcm_in, FRAME_SAMPLES, packet, sizeof(packet));
if (packet_len <= 0) {
printf("FAIL (encode returned %d)\n", packet_len);
opus_codec_encoder_destroy(enc);
opus_codec_decoder_destroy(dec);
return 1;
}
printf("encoded silence: %d bytes, ", packet_len);
int16_t pcm_out[FRAME_SAMPLES];
int decoded = opus_codec_decode(dec, packet, packet_len, pcm_out, FRAME_SAMPLES);
if (decoded != FRAME_SAMPLES) {
printf("FAIL (decode returned %d, expected %d)\n", decoded, FRAME_SAMPLES);
opus_codec_encoder_destroy(enc);
opus_codec_decoder_destroy(dec);
return 1;
}
printf("decoded %d samples -> PASS\n", decoded);
opus_codec_encoder_destroy(enc);
opus_codec_decoder_destroy(dec);
return 0;
}
static int test_encode_decode_sine(void) {
printf("test_encode_decode_sine: ");
opus_codec_encoder_t* enc = opus_codec_encoder_create(SAMPLE_RATE, CHANNELS);
if (!enc) { printf("FAIL (encoder_create)\n"); return 1; }
opus_codec_decoder_t* dec = opus_codec_decoder_create(SAMPLE_RATE, CHANNELS);
if (!dec) { printf("FAIL (decoder_create)\n"); opus_codec_encoder_destroy(enc); return 1; }
int ok = 1;
int nframes = 10;
for (int frame = 0; frame < nframes; frame++) {
int16_t pcm_in[FRAME_SAMPLES];
for (int i = 0; i < FRAME_SAMPLES; i++) {
long gi = (long)frame * FRAME_SAMPLES + i;
pcm_in[i] = (int16_t)(10000.0 * sin(2.0 * M_PI * 440.0 * gi / SAMPLE_RATE));
}
uint8_t packet[4000];
int packet_len = opus_codec_encode(enc, pcm_in, FRAME_SAMPLES, packet, sizeof(packet));
if (packet_len <= 0) { printf("FAIL (encode frame %d returned %d)\n", frame, packet_len); ok = 0; break; }
int16_t pcm_out[FRAME_SAMPLES * 2];
int decoded = opus_codec_decode(dec, packet, packet_len, pcm_out, FRAME_SAMPLES);
if (decoded <= 0) { printf("FAIL (decode frame %d returned %d)\n", frame, decoded); ok = 0; break; }
/* verify output has energy (not all zeros) */
if (frame >= 2) {
int energy = 0;
for (int i = 0; i < decoded && i < FRAME_SAMPLES * 2; i++)
energy += abs(pcm_out[i]);
if (energy == 0) { printf("FAIL (frame %d output is silent)\n", frame); ok = 0; break; }
}
}
if (ok) printf("%d frames encoded/decoded -> PASS\n", nframes);
opus_codec_encoder_destroy(enc);
opus_codec_decoder_destroy(dec);
return ok ? 0 : 1;
}
static int test_compression_ratio(void) {
printf("test_compression_ratio: ");
opus_codec_encoder_t* enc = opus_codec_encoder_create(SAMPLE_RATE, CHANNELS);
if (!enc) { printf("FAIL (encoder_create)\n"); return 1; }
int16_t pcm_in[FRAME_SAMPLES];
for (int i = 0; i < FRAME_SAMPLES; i++) {
pcm_in[i] = (int16_t)(16000.0 * sin(2.0 * M_PI * 200.0 * i / SAMPLE_RATE));
}
uint8_t packet[4000];
int packet_len = opus_codec_encode(enc, pcm_in, FRAME_SAMPLES, packet, sizeof(packet));
int pcm_size = FRAME_SAMPLES * sizeof(int16_t);
if (packet_len <= 0) {
printf("FAIL (encode returned %d)\n", packet_len);
opus_codec_encoder_destroy(enc);
return 1;
}
if (packet_len >= pcm_size) {
printf("FAIL (packet %d bytes >= PCM %d bytes, no compression)\n", packet_len, pcm_size);
opus_codec_encoder_destroy(enc);
return 1;
}
printf("compression: PCM %d bytes -> Opus %d bytes (%.1fx) -> PASS\n",
pcm_size, packet_len, (double)pcm_size / packet_len);
opus_codec_encoder_destroy(enc);
return 0;
}
static int test_plc(void) {
printf("test_plc: ");
opus_codec_decoder_t* dec = opus_codec_decoder_create(SAMPLE_RATE, CHANNELS);
if (!dec) { printf("FAIL (decoder_create)\n"); return 1; }
int16_t pcm_out[FRAME_SAMPLES * 2];
int decoded = opus_codec_decode(dec, NULL, 0, pcm_out, FRAME_SAMPLES);
if (decoded <= 0) {
printf("FAIL (PLC returned %d)\n", decoded);
opus_codec_decoder_destroy(dec);
return 1;
}
printf("PLC returned %d samples -> PASS\n", decoded);
opus_codec_decoder_destroy(dec);
return 0;
}
static int test_null_args(void) {
printf("test_null_args: ");
int r = opus_codec_encode(NULL, NULL, 0, NULL, 0);
if (r >= 0) { printf("FAIL (expected error)\n"); return 1; }
r = opus_codec_decode(NULL, NULL, 0, NULL, 0);
if (r >= 0) { printf("FAIL (expected error)\n"); return 1; }
opus_codec_encoder_destroy(NULL);
opus_codec_decoder_destroy(NULL);
printf("PASS\n");
return 0;
}
static int test_default_sample_rate(void) {
printf("test_default_sample_rate: ");
opus_codec_encoder_t* enc = opus_codec_encoder_create(0, 0);
if (!enc) { printf("FAIL (encoder_create)\n"); return 1; }
opus_codec_decoder_t* dec = opus_codec_decoder_create(0, 0);
if (!dec) { printf("FAIL (decoder_create)\n"); opus_codec_encoder_destroy(enc); return 1; }
/* 20ms at default 48kHz = 960 samples */
int16_t pcm[960];
memset(pcm, 0, sizeof(pcm));
uint8_t packet[4000];
int encoded = opus_codec_encode(enc, pcm, 960, packet, sizeof(packet));
if (encoded <= 0) { printf("FAIL (encode)\n"); opus_codec_encoder_destroy(enc); opus_codec_decoder_destroy(dec); return 1; }
int decoded = opus_codec_decode(dec, packet, encoded, pcm, 960);
if (decoded != 960) { printf("FAIL (decode returned %d)\n", decoded); opus_codec_encoder_destroy(enc); opus_codec_decoder_destroy(dec); return 1; }
printf("PASS\n");
opus_codec_encoder_destroy(enc);
opus_codec_decoder_destroy(dec);
return 0;
}
static int test_multiple_frames(void) {
printf("test_multiple_frames: ");
opus_codec_encoder_t* enc = opus_codec_encoder_create(SAMPLE_RATE, CHANNELS);
opus_codec_decoder_t* dec = opus_codec_decoder_create(SAMPLE_RATE, CHANNELS);
if (!enc || !dec) { printf("FAIL (create)\n"); opus_codec_encoder_destroy(enc); opus_codec_decoder_destroy(dec); return 1; }
int ok = 1;
for (int frame = 0; frame < 10; frame++) {
int16_t pcm_in[FRAME_SAMPLES];
double freq = 200.0 + frame * 50.0;
for (int i = 0; i < FRAME_SAMPLES; i++) {
pcm_in[i] = (int16_t)(8000.0 * sin(2.0 * M_PI * freq * i / SAMPLE_RATE));
}
uint8_t packet[4000];
int len = opus_codec_encode(enc, pcm_in, FRAME_SAMPLES, packet, sizeof(packet));
if (len <= 0) { printf("FAIL (encode frame %d)\n", frame); ok = 0; break; }
int16_t pcm_out[FRAME_SAMPLES];
int decoded = opus_codec_decode(dec, packet, len, pcm_out, FRAME_SAMPLES);
if (decoded != FRAME_SAMPLES) { printf("FAIL (decode frame %d returned %d)\n", frame, decoded); ok = 0; break; }
}
if (ok) printf("PASS\n");
opus_codec_encoder_destroy(enc);
opus_codec_decoder_destroy(dec);
return ok ? 0 : 1;
}
int main(void) {
int failed = 0;
failed += test_encode_decode_silence();
failed += test_encode_decode_sine();
failed += test_compression_ratio();
failed += test_plc();
failed += test_null_args();
failed += test_default_sample_rate();
failed += test_multiple_frames();
printf("\n%s: %d/%d tests passed\n", failed ? "FAIL" : "OK", 7 - failed, 7);
return failed ? 1 : 0;
}