/*
* note.cc
* DIN Is Noise is copyright (c) 2006-2022 Jagannathan Sampath
* DIN Is Noise is released under GNU Public License 2.0
* For more information, please visit https://dinisnoise.org/
*/

#include "note.h"
#include "main.h"
#include "scale_info.h"
#include "utils.h"
#include <math.h>
#include <map>

extern char BUFFER [];
extern const char spc;
extern int NOTATION;

note::note () {
  hz = 0;
  step = 0;
	scale_pos = 0;
	octave = 0;
}

void note::set_freq (float f) {
  hz = f;
  hz2step (hz, step);
	sprintf (BUFFER, "%0.3f", hz);
	hz_name = BUFFER;
}

void note::set_freq (float key, float interval) {
	set_freq (key * interval * pow (2.0, octave));
}

void note::set_name (const std::string& n) {
  name = n;
}

void note::set_name (const std::string& interval, int offset) {
	if (NOTATION == WESTERN) {
		extern std::map<std::string, int> NOTE_POS;
		extern const char* WESTERN_FLAT [];
		int np = NOTE_POS[interval];
		name = WESTERN_FLAT[(offset + np) % 12];
	} else if (NOTATION == NUMERIC) {
		set_name (interval);
	} else {
    extern map<string, string> INT2IND;
    set_name (INT2IND[interval]);
  }
}

void note::change_scale_pos (int j, scale_info& si) {
  int i = sign(j);
  int k = abs(j);
  while (k--) {
    scale_pos += i;
    if (scale_pos < 0) {
      scale_pos = si.second_last_note; 
      --octave;
    }
    else if (scale_pos > si.last_note) {
      scale_pos = 1;
      ++octave;
    }
  }
}

std::ofstream& note::save (std::ofstream& f) {
	f << name << spc << hz_name << spc << hz << spc << step << spc << scale_pos << spc << octave << spc;
	return f;
}

std::ifstream& note::load (std::ifstream& f) {
	f >> name >> hz_name >> hz >> step >> scale_pos >> octave;
	return f;
}
