Last commit for src/lingot-config-scale.c: c04af18902322cea1bd05b6f01b7860ca7bfa432

- import version 0.9.1 from upstream

Piotr Pawlow [2014-03-13 19:51:31]
- import version 0.9.1 from upstream
/*
 * lingot, a musical instrument tuner.
 *
 * Copyright (C) 2004-2011  Ibán Cereijo Graña, Jairo Chapela Martínez.
 *
 * This file is part of lingot.
 *
 * lingot is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * lingot is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with lingot; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#include "lingot-config-scale.h"

LingotScale* lingot_config_scale_new() {

	LingotScale* scale = malloc(sizeof(LingotScale));

	scale->name = NULL;
	scale->notes = 0;
	scale->note_name = NULL;
	scale->offset_cents = NULL;
	scale->offset_ratios[0] = NULL;
	scale->offset_ratios[1] = NULL;
	scale->base_frequency = 0.0;

	return scale;
}

void lingot_config_scale_allocate(LingotScale* scale, unsigned short int notes) {
	scale->notes = notes;
	scale->note_name = malloc(notes * sizeof(char*));
	scale->offset_cents = malloc(notes * sizeof(FLT));
	scale->offset_ratios[0] = malloc(notes * sizeof(short int));
	scale->offset_ratios[1] = malloc(notes * sizeof(short int));
}

void lingot_config_scale_destroy(LingotScale* scale) {
	unsigned short int i;
	for (i = 0; i < scale->notes; i++) {
		free(scale->note_name[i]);
	}

	if (scale->offset_cents != NULL)
		free(scale->offset_cents);

	if (scale->offset_ratios[0] != NULL)
		free(scale->offset_ratios[0]);
	if (scale->offset_ratios[1] != NULL)
		free(scale->offset_ratios[1]);

	if (scale->note_name != NULL)
		free(scale->note_name);
	if (scale->name != NULL)
		free(scale->name);

	scale->name = NULL;
	scale->notes = 0;
	scale->note_name = NULL;
	scale->offset_cents = NULL;
	scale->offset_ratios[0] = NULL;
	scale->offset_ratios[1] = NULL;
	scale->base_frequency = 0.0;
}

void lingot_config_scale_restore_default_values(LingotScale* scale) {

	unsigned short int i;
	static char* tone_string[] = { "C", "C#", "D", "D#", "E", "F", "F#", "G",
			"G#", "A", "A#", "B", };

	lingot_config_scale_destroy(scale);

	// default 12 tones equal-tempered scale hard-coded
	scale->name = strdup("Default equal-tempered scale");
	lingot_config_scale_allocate(scale, 12);

	scale->base_frequency = MID_C_FREQUENCY;

	scale->note_name[0] = strdup(tone_string[0]);
	scale->offset_cents[0] = 0.0;
	scale->offset_ratios[0][0] = 1;
	scale->offset_ratios[1][0] = 1; // 1/1

	for (i = 1; i < scale->notes; i++) {
		scale->note_name[i] = strdup(tone_string[i]);
		scale->offset_cents[i] = 100.0 * i;
		scale->offset_ratios[0][i] = -1; // not used
		scale->offset_ratios[1][i] = -1; // not used
	}
}

void lingot_config_scale_copy(LingotScale* dst, LingotScale* src) {
	unsigned short int i;

	lingot_config_scale_destroy(dst);

	*dst = *src;

	dst->name = strdup(src->name);
	lingot_config_scale_allocate(dst, dst->notes);

	for (i = 0; i < dst->notes; i++) {
		dst->note_name[i] = strdup(src->note_name[i]);
		dst->offset_cents[i] = src->offset_cents[i];
		dst->offset_ratios[0][i] = src->offset_ratios[0][i];
		dst->offset_ratios[1][i] = src->offset_ratios[1][i];
	}
}

int lingot_config_scale_parse_shift(char* char_buffer, double* cents,
		short int* numerator, short int* denominator) {
	const static char* delim = "/";
	char* char_buffer_pointer1 = strtok(char_buffer, delim);
	char* char_buffer_pointer2 = strtok(NULL, delim);
	short int num, den;
	int result = 1;

	if (numerator != NULL) {
		*numerator = -1;
	}

	if (denominator != NULL) {
		*denominator = -1;
	}

	int n = 0;
	if (!char_buffer_pointer2) {
		n = sscanf(char_buffer_pointer1, "%lf", cents);
		if (!n) {
			result = 0;
		}
	} else {
		n = sscanf(char_buffer_pointer1, "%hd", &num);
		if (!n) {
			result = 0;
		} else {
			n = sscanf(char_buffer_pointer2, "%hd", &den);
			if (!n) {
				result = 0;
			} else {
				*cents = 1200.0 * log2(1.0 * num / den);
				if (numerator != NULL) {
					*numerator = num;
				}
				if (denominator != NULL) {
					*denominator = den;
				}
			}
		}
	}

	if (!result) {
		*numerator = 1;
		*denominator = 1;
		*cents = 0.0;
	}

	return result;
}

void lingot_config_scale_format_shift(char* char_buffer, double cents,
		short int numerator, short int denominator) {
	if (numerator < 0) {
		sprintf(char_buffer, "%0.4lf", cents);
	} else {
		sprintf(char_buffer, "%hd/%hd", numerator, denominator);
	}
}

int lingot_config_scale_load_scl(LingotScale* scale, char* filename) {
	FILE* fp;
	int i;
	char* char_buffer_pointer1;
	char* nl;
	const static char* delim = " \t\n";
	int result = 1;

#   define MAX_LINE_SIZE 1000

	char char_buffer[MAX_LINE_SIZE];

	if ((fp = fopen(filename, "r")) == NULL) {
		sprintf(char_buffer, "error opening scale file %s", filename);
		perror(char_buffer);
		return 0;
	}

	scale->base_frequency = MID_C_FREQUENCY;

	fgets(char_buffer, MAX_LINE_SIZE, fp);
	if (strchr(char_buffer, '!') != char_buffer) {
		fclose(fp);
		return 0;
	}

	fgets(char_buffer, MAX_LINE_SIZE, fp);
	fgets(char_buffer, MAX_LINE_SIZE, fp);

	nl = strrchr(char_buffer, '\r');
	if (nl)
		*nl = '\0';
	nl = strrchr(char_buffer, '\n');
	if (nl)
		*nl = '\0';
	scale->name = strdup(char_buffer);

	fgets(char_buffer, MAX_LINE_SIZE, fp);
	sscanf(char_buffer, "%hu", &scale->notes);

	fgets(char_buffer, MAX_LINE_SIZE, fp);
	lingot_config_scale_allocate(scale, scale->notes);

	scale->note_name[0] = strdup("1");
	scale->offset_cents[0] = 0.0;
	scale->offset_ratios[0][0] = 1;
	scale->offset_ratios[1][0] = 1; // 1/1

	for (i = 1; i < scale->notes; i++) {

		fgets(char_buffer, MAX_LINE_SIZE, fp);

		char_buffer_pointer1 = strtok(char_buffer, delim);

		int r = lingot_config_scale_parse_shift(char_buffer_pointer1,
				&scale->offset_cents[i], &scale->offset_ratios[0][i],
				&scale->offset_ratios[1][i]);
		if (!r) {
			result = 0;
		}

		sprintf(char_buffer, "%d", i + 1);
		scale->note_name[i] = strdup(char_buffer);
	}

	fclose(fp);

#   undef MAX_LINE_SIZE
	return result;
}
ViewGit