Subversion Repositories DIN Is Noise

Rev

Rev 484 | Rev 913 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
* scale_info.cc
* DIN Is Noise is copyright (c) 2006-2018 Jagannathan Sampath
* For more information, please visit http://dinisnoise.org/
*/



#include "scalelist.h"
#include "scale_info.h"
#include "console.h"
#include "tokenizer.h"
#include "utils.h"
#include "checkbutton.h"
#include "note.h"
#include "settings.h"
#include "ui_list.h"
#include "main.h"

#include <fstream>
#include <vector>
#include <string>
using namespace std;

extern ofstream dlog;
extern string user_data_dir;

extern int NUM_INTERVALS;
extern vector<string> INTERVAL_NAMES;
extern string SCALE;

extern ui_list uis;

extern char BUFFER [];

int scale_info::set_tonic (float f) {
  nearest_note.freq = f;
  nearest_note.distance = 0;
  western = find_nearest_note (nearest_note.name, nearest_note.freq, nearest_note.distance);
  float d2 = nearest_note.distance * nearest_note.distance;
  if (d2 < 0.01) tonic = nearest_note.freq; else tonic = f; // snap to note
  lo_tonic = tonic / 2.0f;
  hi_tonic = tonic * 2.0f;
  if (scl) scl->tonic_changed ();
  return 1;
}

int scale_info::load_scale (const string& n) {

  name = n;

  ifstream file ((user_data_dir + name).c_str(), ios::in);
  if (!file) return 0;

  string ignore;

  file >> ignore >> num_notes >> ignore;

  string nn;
  for (int i = 0; i < num_notes; ++i) {
    file >> nn;
    notes.push_back (nn);
  }

  num_ranges = num_notes - 1;
  last_range = num_ranges - 1;

  // load custom tuning if it exists
  if (load_custom_tuning() == 0) { // no, load default tuning
    extern map<string, float> INTERVALS;
    intervals = INTERVALS;
  }

  if (scl) scl->scale_loaded ();

  return 1;

}

int scale_info::save_scale () {

  string fname (user_data_dir + name);

  ofstream file ((user_data_dir + name).c_str(), ios::out);
  if (!file) return 0;

  file << "num_notes " << num_notes << endl;
  file << "notes ";
  for (int i = 0; i < num_notes; ++i) file << notes[i] << ' ';
  file << endl;

  dlog << "+++ saved scale into " + fname + " +++" << endl;

  return 1;

}

int scale_info::load_custom_tuning () {

  string filename = user_data_dir + name + ".intervals";

  ifstream file (filename.c_str(), ios::in);
  if (!file) {
    dlog << "!!! couldnt load custom tuning from: " << filename << "; will use defaults. +++" << endl;
    return 0;
  }

  string ignore;

  int n;
  file >> ignore >> n;

  for (int i = 0; i < n; ++i) {
    string c;
    float f;
    file >> c >> f;
    intervals [c] = f;
  }

  return 1;


}

void scale_info::save_custom_tuning () {

  string filename = user_data_dir + name + ".intervals";
  ofstream file (filename.c_str(), ios::out);
  if (!file) {
    dlog << "!!! could not save custom tuning in " << filename << " !!!" << endl;
    return;
  }

  file << "num_intervals " << intervals.size () << endl;
  for (map<string, float>::iterator i = intervals.begin(), j = intervals.end(); i != j; ++i) {
    pair<string, float> p = *i;
    file << p.first << ' ' << p.second << endl;
  }

}

void scale_info::update (checkbutton* cb_notes) {
  notes.clear ();
  name.clear ();
  for (int i = 0; i < NUM_INTERVALS; ++i) {
    if (cb_notes[i].is_on ()) {
      const string& in = INTERVAL_NAMES[i];
      notes.push_back (in);
      name += in;
    }
  }
  num_notes = notes.size ();
  num_ranges = num_notes - 1;
  last_range = num_ranges - 1;
  if (scl) scl->scale_changed ();
  SCALE = name;
}

void scale_info::update_settings () {
  sprintf (BUFFER, " nearest note = %s @ %0.3f Hz", nearest_note.name.c_str (), nearest_note.freq);
  uis.settings_scr.ol_nearest_note.option.set_text (BUFFER);
  uis.settings_scr.s_key.set_value (tonic);
  uis.settings_scr.sn_scale_notes.refresh ();
}