raze-gles/source/libxmp-lite/src/period.c
terminx 8de955053c Update libxmp-lite
git-svn-id: https://svn.eduke32.com/eduke32@8132 1a8010ca-5511-0410-912e-c29ae57300e0
2019-09-20 23:29:40 +02:00

268 lines
6.8 KiB
C

/* Extended Module Player
* Copyright (C) 1996-2018 Claudio Matsuoka and Hipolito Carraro Jr
*
* 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__)
static inline double libxmp_round(double val)
{
return (val >= 0.0)? floor(val + 0.5) : ceil(val - 0.5);
}
#else
#define libxmp_round round
#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;
}
return libxmp_round(12.0 * log(PERIOD_BASE / p) / M_LN2) + 1;
}
/* 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:
return (int) (100 * (8 * (((240 - n) << 4) - p)));
case PERIOD_CSPD:
d = libxmp_note_to_period(ctx, n, 0, adj);
return libxmp_round(100.0 * (1536.0 / M_LN2) * log(p / d));
default:
/* Amiga */
d = libxmp_note_to_period(ctx, n, 0, adj);
return libxmp_round(100.0 * (1536.0 / M_LN2) * log(d / p));
}
}
/* 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;
}