<commit_before>#include "eval.hh"
#include "live.hh"
#include "utils.hh"
#include "gfx.hh"
#include "lex.hh"
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include "imgui.hh"
#include "../thirdparty/imgui/imgui.h"
#include <thread>
#include <atomic>
#include <fstream>

void reload_file();
void replot();
void recalculate_freq_to_note();
void compute();
void compute_single();
void save();

struct passed_data_t {
  struct note_data_t {
    bool on;
    uint64_t c;
    note_data_t() : on(false), c(0) {}
  };
  term_t *program;
  std::string definition;
  std::map<int, note_data_t> notes; // kinda sloppy but works
  passed_data_t()
    : program(nullptr)
    , definition("") {
  }
};

const float sample_rate = 48000, num_computed_seconds = 1.2;
const int num_computed_samples = sample_rate * num_computed_seconds + 0.5f;
const std::map<int, std::pair<char, int>> key_notes = {
  { SDLK_a, { 'C', 0 } },
  { SDLK_w, { 'C', 1 } },
  { SDLK_s, { 'D', 0 } },
  { SDLK_e, { 'D', 1 } },
  { SDLK_d, { 'E', 0 } },
  { SDLK_f, { 'F', 0 } },
  { SDLK_t, { 'F', 1 } },
  { SDLK_g, { 'G', 0 } },
  { SDLK_y, { 'G', 1 } },
  { SDLK_h, { 'A', 0 } },
  { SDLK_u, { 'A', 1 } },
  { SDLK_j, { 'B', 0 } }
};
enum class computing_status_t {
  not_computed,
  computing,
  stopped,
  single_computed,
  computed
};
// note idx: [0; 120): # of semitones above C0 (to encode absolute note to int)
// note char: 'C', 'A'...: literal char

static bool g_done = false, g_show_test_window = false;
static SDL_AudioDeviceID g_dev = 0;
static std::string g_filename = "";
static char g_source[100000]; // stupid
static passed_data_t *g_passed_data = nullptr;
static std::vector<message_t> g_messages;
static std::vector<float> g_samples;
static float g_volume = 20.f, g_frequency = 55.f /* A1 */, g_seconds = 1;
static std::string g_frequency_to_note = "";
static int g_octave = 4;
static bool playing = true, unsaved = false;
static std::vector<std::string> g_definition_list;
static int g_definition_list_selected_idx = -1;
static float computed_samples[120][num_computed_samples]
  , single_computed_samples[num_computed_samples];
static double computation_progress = 0, g_time = 0, g_computation_time_started = 0;
static std::thread *computation_thread = nullptr;
static std::atomic<computing_status_t> computing_status {
  computing_status_t::not_computed };

static int note_details_to_note_idx(char note, int octave, int accidental_offset) {
  const std::map<char, int> note_char_semitone_offset = {
    { 'C', -9 },
    { 'D', -7 },
    { 'E', -5 },
    { 'F', -4 },
    { 'G', -2 },
    { 'A',  0 },
    { 'B',  2 }
  };
  return octave * 12 + note_char_semitone_offset.at(note) + 9 + accidental_offset;
}

bool definition_list_getter(void *data, int idx, const char **out_text) {
  std::vector<std::string> *defs = (std::vector<std::string>*)data;
  if (idx < (int)defs->size()) {
    *out_text = defs->at(idx).c_str();
    return true;
  }
  return false;
}

// TODO: LUT
static double note_idx_to_freq(int note_idx) {
  int octave = note_idx / 12, semitone_in_octave = note_idx - octave * 12
    , octave_offset = octave - 4, semitone_offset = semitone_in_octave - 9;
  return 440. * pow(2., octave_offset) * pow(2., semitone_offset / 12.);
}

static void audio_callback(void *userdata, uint8_t *stream, int len) {
  passed_data_t *passed_data = (passed_data_t*)userdata;
  float *stream_ptr = (float*)stream;
  for (int i = 0; i < 4096; ++i) {
    *stream_ptr = 0;
    if (passed_data->definition == ""
        || computing_status == computing_status_t::computing) {
      ++stream_ptr;
      continue;
    }
    for (auto &freq_pair : passed_data->notes) {
      if (!freq_pair.second.on)
        continue;
      if (computing_status == computing_status_t::computed
          || computing_status == computing_status_t::single_computed)
        *stream_ptr += g_volume / 100.f
          * computed_samples[freq_pair.first][freq_pair.second.c];
      else
        *stream_ptr += g_volume / 100.f
          * (float)evaluate_definition(passed_data->program
          , passed_data->definition, note_idx_to_freq(freq_pair.first)
          , (float)(freq_pair.second.c) / sample_rate);
      if (freq_pair.second.c < num_computed_samples)
        ++freq_pair.second.c;
    }
    ++stream_ptr;
  }
}

static ImVec4 r2v(int r, int g, int b) {
  return ImVec4((float)r / 255.f, (float)g / 255.f, (float)b / 255.f, 1.f);
}

static void init() {
  SDL_AudioSpec want, have;<commit_msg>Fix computed samples clipping & compute 1.2s -> 2s<commit_after>#include "eval.hh"
#include "live.hh"
#include "utils.hh"
#include "gfx.hh"
#include "lex.hh"
#include <SDL2/SDL.h>
#include <GL/glew.h>
#include "imgui.hh"
#include "../thirdparty/imgui/imgui.h"
#include <thread>
#include <atomic>
#include <fstream>

void reload_file();
void replot();
void recalculate_freq_to_note();
void compute();
void compute_single();
void save();

struct passed_data_t {
  struct note_data_t {
    bool on;
    uint64_t c;
    note_data_t() : on(false), c(0) {}
  };
  term_t *program;
  std::string definition;
  std::map<int, note_data_t> notes; // kinda sloppy but works
  passed_data_t()
    : program(nullptr)
    , definition("") {
  }
};

const float sample_rate = 48000, num_computed_seconds = 2;
const int num_computed_samples = sample_rate * num_computed_seconds + 0.5f;
const std::map<int, std::pair<char, int>> key_notes = {
  { SDLK_a, { 'C', 0 } },
  { SDLK_w, { 'C', 1 } },
  { SDLK_s, { 'D', 0 } },
  { SDLK_e, { 'D', 1 } },
  { SDLK_d, { 'E', 0 } },
  { SDLK_f, { 'F', 0 } },
  { SDLK_t, { 'F', 1 } },
  { SDLK_g, { 'G', 0 } },
  { SDLK_y, { 'G', 1 } },
  { SDLK_h, { 'A', 0 } },
  { SDLK_u, { 'A', 1 } },
  { SDLK_j, { 'B', 0 } }
};
enum class computing_status_t {
  not_computed,
  computing,
  stopped,
  single_computed,
  computed
};
// note idx: [0; 120): # of semitones above C0 (to encode absolute note to int)
// note char: 'C', 'A'...: literal char

static bool g_done = false, g_show_test_window = false;
static SDL_AudioDeviceID g_dev = 0;
static std::string g_filename = "";
static char g_source[100000]; // stupid
static passed_data_t *g_passed_data = nullptr;
static std::vector<message_t> g_messages;
static std::vector<float> g_samples;
static float g_volume = 20.f, g_frequency = 55.f /* A1 */, g_seconds = 1;
static std::string g_frequency_to_note = "";
static int g_octave = 4;
static bool playing = true, unsaved = false;
static std::vector<std::string> g_definition_list;
static int g_definition_list_selected_idx = -1;
static float computed_samples[120][num_computed_samples]
  , single_computed_samples[num_computed_samples];
static double computation_progress = 0, g_time = 0, g_computation_time_started = 0;
static std::thread *computation_thread = nullptr;
static std::atomic<computing_status_t> computing_status {
  computing_status_t::not_computed };

static int note_details_to_note_idx(char note, int octave, int accidental_offset) {
  const std::map<char, int> note_char_semitone_offset = {
    { 'C', -9 },
    { 'D', -7 },
    { 'E', -5 },
    { 'F', -4 },
    { 'G', -2 },
    { 'A',  0 },
    { 'B',  2 }
  };
  return octave * 12 + note_char_semitone_offset.at(note) + 9 + accidental_offset;
}

bool definition_list_getter(void *data, int idx, const char **out_text) {
  std::vector<std::string> *defs = (std::vector<std::string>*)data;
  if (idx < (int)defs->size()) {
    *out_text = defs->at(idx).c_str();
    return true;
  }
  return false;
}

// TODO: LUT
static double note_idx_to_freq(int note_idx) {
  int octave = note_idx / 12, semitone_in_octave = note_idx - octave * 12
    , octave_offset = octave - 4, semitone_offset = semitone_in_octave - 9;
  return 440. * pow(2., octave_offset) * pow(2., semitone_offset / 12.);
}

static void audio_callback(void *userdata, uint8_t *stream, int len) {
  passed_data_t *passed_data = (passed_data_t*)userdata;
  float *stream_ptr = (float*)stream;
  for (int i = 0; i < 4096; ++i) {
    *stream_ptr = 0;
    if (passed_data->definition == ""
        || computing_status == computing_status_t::computing) {
      ++stream_ptr;
      continue;
    }
    for (auto &freq_pair : passed_data->notes) {
      if (!freq_pair.second.on)
        continue;
      if (computing_status == computing_status_t::computed
          || computing_status == computing_status_t::single_computed)
        *stream_ptr += g_volume / 100.f
          * computed_samples[freq_pair.first][freq_pair.second.c];
      else
        *stream_ptr += g_volume / 100.f
          * (float)evaluate_definition(passed_data->program
          , passed_data->definition, note_idx_to_freq(freq_pair.first)
          , (float)(freq_pair.second.c) / sample_rate);
      if (freq_pair.second.c < num_computed_samples - 1)
        ++freq_pair.second.c;
    }
    ++stream_ptr;
  }
}

static ImVec4 r2v(int r, int g, int b) {
  return ImVec4((float)r / 255.f, (float)g / 255.f, (float)b / 255.f, 1.f);
}

static void init() {
  SDL_AudioSpec want, have;
{'fraction_non_alphanumeric': 0.15322850451656073, 'fraction_numerical': 0.02263856362217018, 'mean_word_length': 3.7224855186940493, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4955790', 'n_tokens_mistral': 3565, 'n_tokens_neox': 3358, 'n_words': 762}