summaryrefslogtreecommitdiff
path: root/src/audio/ola.cc
blob: fd5098e7390555aacf610bf4eeea3ec0e37fff31 (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
// This file is part of the 64k demo project.
// Implements batch OLA encode/decode shared by spectool and tests.
// See ola.h for API documentation.

#include "audio/ola.h"
#include "audio/window.h"
#include <string.h>

void ola_encode(const float* pcm, int n_samples, float* spec, int num_frames) {
  float win[DCT_SIZE];
  hann_window_512(win);
  float chunk[DCT_SIZE];
  for (int f = 0; f < num_frames; ++f) {
    const int start = f * OLA_HOP_SIZE;
    const int avail =
        (start + DCT_SIZE <= n_samples) ? DCT_SIZE : n_samples - start;
    for (int i = 0; i < avail; ++i)
      chunk[i] = pcm[start + i] * win[i];
    memset(chunk + avail, 0, (DCT_SIZE - avail) * sizeof(float));
    fdct_512(chunk, spec + f * DCT_SIZE);
  }
}

void ola_decode_frame(const float* spec_frame, float* overlap, float* out_hop) {
  float tmp[DCT_SIZE];
  idct_512(spec_frame, tmp);
  for (int j = 0; j < OLA_HOP_SIZE; ++j)
    out_hop[j] = tmp[j] + overlap[j];
  for (int j = 0; j < OLA_OVERLAP; ++j)
    overlap[j] = tmp[OLA_HOP_SIZE + j];
}

void ola_decode(const float* spec, int num_frames, float* pcm) {
  float overlap[OLA_OVERLAP] = {};
  for (int f = 0; f < num_frames; ++f) {
    ola_decode_frame(spec + f * DCT_SIZE, overlap, pcm + f * OLA_HOP_SIZE);
  }
}