summaryrefslogtreecommitdiff
path: root/src/tests/test_spectool.cc
blob: 7581f0d9ca6b1a9a5440557713f26e2ae78df056 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include "audio/dct.h" // For DCT_SIZE
#include "miniaudio.h"
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h> // For system()
#include <vector>

// Re-defining the header here to avoid dependency on the tool's source
struct SpecHeader {
  char magic[4];
  int32_t version;
  int32_t dct_size;
  int32_t num_frames;
};

#define TEST_SAMPLE_RATE 32000
#define TEST_DURATION_SECONDS 1
#define TEST_FREQ 440.0f
#define PI 3.14159265f

int main() {
  printf("Running spectool end-to-end test...\n");

  const char *wav_path = "test_signal.wav";
  const char *spec_path = "test_signal.spec";
  const char *spectool_path =
      "./spectool"; // Assumes ctest is run from `build` dir

  // 1. Generate and save a WAV file
  ma_encoder_config enc_config = ma_encoder_config_init(
      ma_encoding_format_wav, ma_format_f32, 1, TEST_SAMPLE_RATE);
  ma_encoder encoder;
  if (ma_encoder_init_file(wav_path, &enc_config, &encoder) != MA_SUCCESS) {
    printf("TEST FAILED: Could not initialize WAV encoder.\n");
    return 1;
  }

  std::vector<float> pcm_data(TEST_SAMPLE_RATE * TEST_DURATION_SECONDS);
  for (size_t i = 0; i < pcm_data.size(); ++i) {
    pcm_data[i] = 0.5f * sinf(2.0f * PI * TEST_FREQ * i / TEST_SAMPLE_RATE);
  }
  ma_uint64 frames_written;
  ma_encoder_write_pcm_frames(&encoder, pcm_data.data(), pcm_data.size(),
                              &frames_written);
  ma_encoder_uninit(&encoder);
  printf("  Generated %s\n", wav_path);

  // 2. Run spectool analyze
  char command[512];
  snprintf(command, sizeof(command), "%s analyze %s %s", spectool_path,
           wav_path, spec_path);
  printf("  Executing: %s\n", command);
  int return_code = system(command);
  assert(return_code == 0);
  printf("  spectool executed successfully.\n");

  // 3. Verify the output .spec file
  FILE *f_spec = fopen(spec_path, "rb");
  assert(f_spec != NULL);

  SpecHeader header;
  fread(&header, sizeof(SpecHeader), 1, f_spec);
  assert(strncmp(header.magic, "SPEC", 4) == 0);
  assert(header.version == 1);
  assert(header.dct_size == DCT_SIZE);

  int expected_frames = (TEST_SAMPLE_RATE * TEST_DURATION_SECONDS) / DCT_SIZE;
  if ((TEST_SAMPLE_RATE * TEST_DURATION_SECONDS) % DCT_SIZE != 0) {
    expected_frames++;
  }
  assert(header.num_frames == expected_frames);

  printf("  .spec header verified.\n");

  // Just check that we have some non-zero data
  std::vector<float> spec_data(header.num_frames * header.dct_size);
  fread(spec_data.data(), sizeof(float), spec_data.size(), f_spec);
  fclose(f_spec);

  double total_energy = 0.0;
  for (float val : spec_data) {
    total_energy += fabs(val);
  }
  assert(total_energy > 0.0);
  printf("  .spec data seems valid.\n");

  // 4. Cleanup
  remove(wav_path);
  remove(spec_path);
  printf("  Cleaned up temporary files.\n");

  printf("...spectool test PASSED!\n");
  return 0;
}