2017-06-09 06:39:37 +00:00
|
|
|
/* Extended Module Player
|
2019-09-20 06:41:07 +00:00
|
|
|
* Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr
|
2017-06-09 06:39:37 +00:00
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included in
|
|
|
|
* all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
* THE SOFTWARE.
|
|
|
|
*/
|
|
|
|
#ifndef _GNU_SOURCE
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "common.h"
|
|
|
|
#include "period.h"
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#ifdef LIBXMP_PAULA_SIMULATOR
|
|
|
|
/*
|
|
|
|
* Period table from the Protracker V2.1A play routine
|
|
|
|
*/
|
|
|
|
static uint16 pt_period_table[16][36] = {
|
|
|
|
/* Tuning 0, Normal */
|
|
|
|
{
|
|
|
|
856,808,762,720,678,640,604,570,538,508,480,453,
|
|
|
|
428,404,381,360,339,320,302,285,269,254,240,226,
|
|
|
|
214,202,190,180,170,160,151,143,135,127,120,113
|
|
|
|
},
|
|
|
|
/* Tuning 1 */
|
|
|
|
{
|
|
|
|
850,802,757,715,674,637,601,567,535,505,477,450,
|
|
|
|
425,401,379,357,337,318,300,284,268,253,239,225,
|
|
|
|
213,201,189,179,169,159,150,142,134,126,119,113
|
|
|
|
},
|
|
|
|
/* Tuning 2 */
|
|
|
|
{
|
|
|
|
844,796,752,709,670,632,597,563,532,502,474,447,
|
|
|
|
422,398,376,355,335,316,298,282,266,251,237,224,
|
|
|
|
211,199,188,177,167,158,149,141,133,125,118,112
|
|
|
|
},
|
|
|
|
/* Tuning 3 */
|
|
|
|
{
|
|
|
|
838,791,746,704,665,628,592,559,528,498,470,444,
|
|
|
|
419,395,373,352,332,314,296,280,264,249,235,222,
|
|
|
|
209,198,187,176,166,157,148,140,132,125,118,111
|
|
|
|
},
|
|
|
|
/* Tuning 4 */
|
|
|
|
{
|
|
|
|
832,785,741,699,660,623,588,555,524,495,467,441,
|
|
|
|
416,392,370,350,330,312,294,278,262,247,233,220,
|
|
|
|
208,196,185,175,165,156,147,139,131,124,117,110
|
|
|
|
},
|
|
|
|
/* Tuning 5 */
|
|
|
|
{
|
|
|
|
826,779,736,694,655,619,584,551,520,491,463,437,
|
|
|
|
413,390,368,347,328,309,292,276,260,245,232,219,
|
|
|
|
206,195,184,174,164,155,146,138,130,123,116,109
|
|
|
|
},
|
|
|
|
/* Tuning 6 */
|
|
|
|
{
|
|
|
|
820,774,730,689,651,614,580,547,516,487,460,434,
|
|
|
|
410,387,365,345,325,307,290,274,258,244,230,217,
|
|
|
|
205,193,183,172,163,154,145,137,129,122,115,109
|
|
|
|
},
|
|
|
|
/* Tuning 7 */
|
|
|
|
{
|
|
|
|
814,768,725,684,646,610,575,543,513,484,457,431,
|
|
|
|
407,384,363,342,323,305,288,272,256,242,228,216,
|
|
|
|
204,192,181,171,161,152,144,136,128,121,114,108
|
|
|
|
},
|
|
|
|
/* Tuning -8 */
|
|
|
|
{
|
|
|
|
907,856,808,762,720,678,640,604,570,538,508,480,
|
|
|
|
453,428,404,381,360,339,320,302,285,269,254,240,
|
|
|
|
226,214,202,190,180,170,160,151,143,135,127,120
|
|
|
|
},
|
|
|
|
/* Tuning -7 */
|
|
|
|
{
|
|
|
|
900,850,802,757,715,675,636,601,567,535,505,477,
|
|
|
|
450,425,401,379,357,337,318,300,284,268,253,238,
|
|
|
|
225,212,200,189,179,169,159,150,142,134,126,119
|
|
|
|
},
|
|
|
|
/* Tuning -6 */
|
|
|
|
{
|
|
|
|
894,844,796,752,709,670,632,597,563,532,502,474,
|
|
|
|
447,422,398,376,355,335,316,298,282,266,251,237,
|
|
|
|
223,211,199,188,177,167,158,149,141,133,125,118
|
|
|
|
},
|
|
|
|
/* Tuning -5 */
|
|
|
|
{
|
|
|
|
887,838,791,746,704,665,628,592,559,528,498,470,
|
|
|
|
444,419,395,373,352,332,314,296,280,264,249,235,
|
|
|
|
222,209,198,187,176,166,157,148,140,132,125,118
|
|
|
|
},
|
|
|
|
/* Tuning -4 */
|
|
|
|
{
|
|
|
|
881,832,785,741,699,660,623,588,555,524,494,467,
|
|
|
|
441,416,392,370,350,330,312,294,278,262,247,233,
|
|
|
|
220,208,196,185,175,165,156,147,139,131,123,117
|
|
|
|
},
|
|
|
|
/* Tuning -3 */
|
|
|
|
{
|
|
|
|
875,826,779,736,694,655,619,584,551,520,491,463,
|
|
|
|
437,413,390,368,347,328,309,292,276,260,245,232,
|
|
|
|
219,206,195,184,174,164,155,146,138,130,123,116
|
|
|
|
},
|
|
|
|
/* Tuning -2 */
|
|
|
|
{
|
|
|
|
868,820,774,730,689,651,614,580,547,516,487,460,
|
|
|
|
434,410,387,365,345,325,307,290,274,258,244,230,
|
|
|
|
217,205,193,183,172,163,154,145,137,129,122,115
|
|
|
|
},
|
|
|
|
/* Tuning -1 */
|
|
|
|
{
|
|
|
|
862,814,768,725,684,646,610,575,543,513,484,457,
|
|
|
|
431,407,384,363,342,323,305,288,272,256,242,228,
|
|
|
|
216,203,192,181,171,161,152,144,136,128,121,114
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef M_LN2
|
|
|
|
#define M_LN2 0.69314718055994530942
|
|
|
|
#endif
|
|
|
|
#if !defined(HAVE_ROUND) || defined(_MSC_VER) || defined(__WATCOMC__)
|
2019-09-20 06:41:07 +00:00
|
|
|
static inline double libxmp_round(double val)
|
2017-06-09 06:39:37 +00:00
|
|
|
{
|
|
|
|
return (val >= 0.0)? floor(val + 0.5) : ceil(val - 0.5);
|
|
|
|
}
|
2019-09-20 06:41:07 +00:00
|
|
|
#else
|
|
|
|
#define libxmp_round round
|
2017-06-09 06:39:37 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef LIBXMP_PAULA_SIMULATOR
|
|
|
|
/* Get period from note using Protracker tuning */
|
|
|
|
static inline int libxmp_note_to_period_pt(int n, int f)
|
|
|
|
{
|
|
|
|
if (n < MIN_NOTE_MOD || n > MAX_NOTE_MOD) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
n -= 48;
|
|
|
|
f >>= 4;
|
|
|
|
if (f < -8 || f > 7) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (f < 0) {
|
|
|
|
f += 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (int)pt_period_table[f][n];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Get period from note */
|
|
|
|
double libxmp_note_to_period(struct context_data *ctx, int n, int f, double adj)
|
|
|
|
{
|
|
|
|
double d, per;
|
|
|
|
struct module_data *m = &ctx->m;
|
|
|
|
#ifdef LIBXMP_PAULA_SIMULATOR
|
|
|
|
struct player_data *p = &ctx->p;
|
|
|
|
|
|
|
|
/* If mod replayer, modrng and Amiga mixing are active */
|
|
|
|
if (p->flags & XMP_FLAGS_A500) {
|
|
|
|
if (IS_AMIGA_MOD()) {
|
|
|
|
return libxmp_note_to_period_pt(n, f);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
d = (double)n + (double)f / 128;
|
|
|
|
|
|
|
|
switch (m->period_type) {
|
|
|
|
case PERIOD_LINEAR:
|
|
|
|
per = (240.0 - d) * 16; /* Linear */
|
|
|
|
break;
|
|
|
|
case PERIOD_CSPD:
|
|
|
|
per = 8363.0 * pow(2, n / 12) / 32 + f; /* Hz */
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
per = PERIOD_BASE / pow(2, d / 12); /* Amiga */
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef LIBXMP_CORE_PLAYER
|
|
|
|
if (adj > 0.1) {
|
|
|
|
per *= adj;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return per;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* For the software mixer */
|
|
|
|
double libxmp_note_to_period_mix(int n, int b)
|
|
|
|
{
|
|
|
|
double d = (double)n + (double)b / 12800;
|
|
|
|
return PERIOD_BASE / pow(2, d / 12);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Get note from period */
|
|
|
|
/* This function is used only by the MOD loader */
|
|
|
|
int libxmp_period_to_note(int p)
|
|
|
|
{
|
|
|
|
if (p <= 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-20 06:41:07 +00:00
|
|
|
return libxmp_round(12.0 * log(PERIOD_BASE / p) / M_LN2) + 1;
|
2017-06-09 06:39:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get pitchbend from base note and amiga period */
|
|
|
|
int libxmp_period_to_bend(struct context_data *ctx, double p, int n, double adj)
|
|
|
|
{
|
|
|
|
struct module_data *m = &ctx->m;
|
|
|
|
double d;
|
|
|
|
|
|
|
|
if (n == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (m->period_type) {
|
|
|
|
case PERIOD_LINEAR:
|
2017-06-10 08:19:35 +00:00
|
|
|
return (int) (100 * (8 * (((240 - n) << 4) - p)));
|
2017-06-09 06:39:37 +00:00
|
|
|
case PERIOD_CSPD:
|
|
|
|
d = libxmp_note_to_period(ctx, n, 0, adj);
|
2019-09-20 06:41:07 +00:00
|
|
|
return libxmp_round(100.0 * (1536.0 / M_LN2) * log(p / d));
|
2017-06-09 06:39:37 +00:00
|
|
|
default:
|
|
|
|
/* Amiga */
|
|
|
|
d = libxmp_note_to_period(ctx, n, 0, adj);
|
2019-09-20 06:41:07 +00:00
|
|
|
return libxmp_round(100.0 * (1536.0 / M_LN2) * log(d / p));
|
2017-06-09 06:39:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Convert finetune = 1200 * log2(C2SPD/8363))
|
|
|
|
*
|
|
|
|
* c = (1200.0 * log(c2spd) - 1200.0 * log(c4_rate)) / M_LN2;
|
|
|
|
* xpo = c/100;
|
|
|
|
* fin = 128 * (c%100) / 100;
|
|
|
|
*/
|
|
|
|
void libxmp_c2spd_to_note(int c2spd, int *n, int *f)
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
|
|
|
|
if (c2spd == 0) {
|
|
|
|
*n = *f = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
c = (int)(1536.0 * log((double)c2spd / 8363) / M_LN2);
|
|
|
|
*n = c / 128;
|
|
|
|
*f = c % 128;
|
|
|
|
}
|