aboutsummaryrefslogtreecommitdiff
path: root/libopna
diff options
context:
space:
mode:
Diffstat (limited to 'libopna')
-rw-r--r--libopna/opnaadpcm.c8
-rw-r--r--libopna/opnaadpcm.h3
-rw-r--r--libopna/opnadrum.c7
-rw-r--r--libopna/opnadrum.h2
-rw-r--r--libopna/opnafm.c13
-rw-r--r--libopna/opnafm.h3
-rw-r--r--libopna/opnassg.c13
-rw-r--r--libopna/opnassg.h2
8 files changed, 49 insertions, 2 deletions
diff --git a/libopna/opnaadpcm.c b/libopna/opnaadpcm.c
index 68dbae5..361064a 100644
--- a/libopna/opnaadpcm.c
+++ b/libopna/opnaadpcm.c
@@ -35,6 +35,7 @@ void opna_adpcm_reset(struct opna_adpcm *adpcm) {
adpcm->prev_acc = 0;
adpcm->adpcmd = 127;
adpcm->out = 0;
+ leveldata_init(&adpcm->leveldata);
}
static uint32_t addr_conv(const struct opna_adpcm *adpcm, uint16_t a) {
@@ -183,8 +184,14 @@ void opna_adpcm_writereg(struct opna_adpcm *adpcm, unsigned reg, unsigned val) {
void opna_adpcm_mix(struct opna_adpcm *adpcm, int16_t *buf, unsigned samples) {
if (!adpcm->ram) return;
if (!(adpcm->control1 & C1_START)) return;
+ unsigned level = 0;
for (unsigned i = 0; i < samples; i++) {
adpcm_calc(adpcm);
+ {
+ int clevel = adpcm->out>>1;
+ if (clevel < 0) clevel = -clevel;
+ if (((unsigned)clevel) > level) level = clevel;
+ }
if (!adpcm->masked) {
int32_t lo = buf[i*2+0];
int32_t ro = buf[i*2+1];
@@ -199,6 +206,7 @@ void opna_adpcm_mix(struct opna_adpcm *adpcm, int16_t *buf, unsigned samples) {
}
if (!(adpcm->control1 & C1_START)) return;
}
+ leveldata_update(&adpcm->leveldata, level);
}
void opna_adpcm_set_ram_256k(struct opna_adpcm *adpcm, void *ram) {
diff --git a/libopna/opnaadpcm.h b/libopna/opnaadpcm.h
index 42033ad..27a0be3 100644
--- a/libopna/opnaadpcm.h
+++ b/libopna/opnaadpcm.h
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "leveldata/leveldata.h"
#ifdef __cplusplus
extern "C" {
@@ -24,6 +25,8 @@ struct opna_adpcm {
uint16_t adpcmd;
int16_t out;
bool masked;
+ atomic_uint levelvu;
+ struct leveldata leveldata;
};
void opna_adpcm_reset(struct opna_adpcm *adpcm);
diff --git a/libopna/opnadrum.c b/libopna/opnadrum.c
index 1a298af..c3e8d38 100644
--- a/libopna/opnadrum.c
+++ b/libopna/opnadrum.c
@@ -23,6 +23,7 @@ void opna_drum_reset(struct opna_drum *drum) {
drum->drums[d].level = 0;
drum->drums[d].left = false;
drum->drums[d].right = false;
+ leveldata_init(&drum->drums[d].leveldata);
}
drum->total_level = 0;
drum->mask = 0;
@@ -81,6 +82,7 @@ void opna_drum_set_rom(struct opna_drum *drum, void *romptr) {
}
void opna_drum_mix(struct opna_drum *drum, int16_t *buf, int samples) {
+ unsigned levels[6] = {0};
for (int i = 0; i < samples; i++) {
int32_t lo = buf[i*2+0];
int32_t ro = buf[i*2+1];
@@ -91,6 +93,8 @@ void opna_drum_mix(struct opna_drum *drum, int16_t *buf, int samples) {
unsigned level = (drum->drums[d].level^0x1f) + (drum->total_level^0x3f);
co *= 15 - (level&7);
co >>= 1+(level>>3);
+ unsigned outlevel = co > 0 ? co : -co;
+ if (outlevel > levels[d]) levels[d] = outlevel;
if (!(drum->mask & (1u << d))) {
if (drum->drums[d].left) lo += co;
if (drum->drums[d].right) ro += co;
@@ -109,6 +113,9 @@ void opna_drum_mix(struct opna_drum *drum, int16_t *buf, int samples) {
buf[i*2+0] = lo;
buf[i*2+1] = ro;
}
+ for (int d = 0; d < 6; d++) {
+ leveldata_update(&drum->drums[d].leveldata, levels[d]);
+ }
}
void opna_drum_writereg(struct opna_drum *drum, unsigned reg, unsigned val) {
diff --git a/libopna/opnadrum.h b/libopna/opnadrum.h
index 79f95a2..7260995 100644
--- a/libopna/opnadrum.h
+++ b/libopna/opnadrum.h
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "leveldata/leveldata.h"
#ifdef __cplusplus
extern "C" {
@@ -32,6 +33,7 @@ struct opna_drum {
unsigned level;
bool left;
bool right;
+ struct leveldata leveldata;
} drums[6];
unsigned total_level;
int16_t rom_bd[OPNA_ROM_BD_SIZE];
diff --git a/libopna/opnafm.c b/libopna/opnafm.c
index 4e86b80..0d57a98 100644
--- a/libopna/opnafm.c
+++ b/libopna/opnafm.c
@@ -3,6 +3,7 @@
#include "opnatables.h"
+
//#include <stdio.h>
#define printf(...)
@@ -27,6 +28,7 @@ static void opna_fm_slot_reset(struct opna_fm_slot *slot) {
void opna_fm_chan_reset(struct opna_fm_channel *chan) {
+ leveldata_init(&chan->leveldata);
for (int i = 0; i < 4; i++) {
opna_fm_slot_reset(&chan->slot[i]);
}
@@ -595,8 +597,6 @@ static int gcd(int a, int b) {
return b;
}
-
-
void opna_fm_mix(struct opna_fm *fm, int16_t *buf, unsigned samples,
struct oscillodata *oscillo, unsigned offset) {
if (oscillo) {
@@ -620,6 +620,7 @@ void opna_fm_mix(struct opna_fm *fm, int16_t *buf, unsigned samples,
}
}
}
+ unsigned level[6] = {0};
for (unsigned i = 0; i < samples; i++) {
if (!fm->env_div3) {
for (int c = 0; c < 6; c++) {
@@ -639,6 +640,11 @@ void opna_fm_mix(struct opna_fm *fm, int16_t *buf, unsigned samples,
for (int c = 0; c < 6; c++) {
struct opna_fm_frame o = opna_fm_chanout(&fm->channel[c]);
+ unsigned nlevel[2];
+ nlevel[0] = o.data[0] > 0 ? o.data[0] : -o.data[0];
+ nlevel[1] = o.data[1] > 0 ? o.data[1] : -o.data[1];
+ if (nlevel[1] > nlevel[0]) nlevel[0] = nlevel[1];
+ if (nlevel[0] > level[c]) level[c] = nlevel[0];
if (oscillo) oscillo[c].buf[offset+i] = o.data[0] + o.data[1];
// TODO: CSM
if (c == 2 && fm->ch3.mode != CH3_MODE_NORMAL) {
@@ -677,4 +683,7 @@ void opna_fm_mix(struct opna_fm *fm, int16_t *buf, unsigned samples,
}
fm->env_div3--;
}
+ for (int c = 0; c < 6; c++) {
+ leveldata_update(&fm->channel[c].leveldata, level[c]);
+ }
}
diff --git a/libopna/opnafm.h b/libopna/opnafm.h
index 9da143f..359517b 100644
--- a/libopna/opnafm.h
+++ b/libopna/opnafm.h
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "leveldata/leveldata.h"
#ifdef __cplusplus
extern "C" {
@@ -64,6 +65,8 @@ struct opna_fm_channel {
uint8_t fb;
uint16_t fnum;
uint8_t blk;
+
+ struct leveldata leveldata;
};
struct opna_fm {
diff --git a/libopna/opnassg.c b/libopna/opnassg.c
index 86d9c9a..d92a8b8 100644
--- a/libopna/opnassg.c
+++ b/libopna/opnassg.c
@@ -134,6 +134,9 @@ void opna_ssg_resampler_reset(struct opna_ssg_resampler *resampler) {
resampler->buf[i] = 0;
}
resampler->index = 0;
+ for (int c = 0; c < 3; c++) {
+ leveldata_init(&resampler->leveldata[c]);
+ }
}
void opna_ssg_writereg(struct opna_ssg *ssg, unsigned reg, unsigned val) {
@@ -286,6 +289,7 @@ void opna_ssg_mix_55466(
}
}
}
+ unsigned level[3] = {0};
for (int i = 0; i < samples; i++) {
{
int ssg_samples = ((resampler->index + 9)>>1) - ((resampler->index)>>1);
@@ -305,6 +309,12 @@ void opna_ssg_mix_55466(
opna_ssg_sinc_calc_func(resampler->index, resampler->buf, outbuf);
for (int ch = 0; ch < 3; ch++) {
if (oscillo) oscillo[ch].buf[offset+i] = outbuf[ch] >> 15;
+ int32_t nlevel = outbuf[ch];
+ nlevel >>= 16;
+ nlevel *= 13000;
+ nlevel >>= 14;
+ if (nlevel < 0) nlevel = -nlevel;
+ if (((unsigned)nlevel) > level[ch]) level[ch] = nlevel;
if (!(ssg->mask & (1<<ch))) sample += outbuf[ch] >> 2;
}
sample >>= 16;
@@ -322,5 +332,8 @@ void opna_ssg_mix_55466(
buf[i*2+0] = lo;
buf[i*2+1] = ro;
}
+ for (int c = 0; c < 3; c++) {
+ leveldata_update(&resampler->leveldata[c], level[c]);
+ }
}
#undef BUFINDEX
diff --git a/libopna/opnassg.h b/libopna/opnassg.h
index 8af8429..3077d08 100644
--- a/libopna/opnassg.h
+++ b/libopna/opnassg.h
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <stdbool.h>
+#include "leveldata/leveldata.h"
#ifdef __cplusplus
extern "C" {
@@ -35,6 +36,7 @@ struct opna_ssg {
struct opna_ssg_resampler {
int16_t buf[OPNA_SSG_SINCTABLELEN*4 * 2];
unsigned index;
+ struct leveldata leveldata[3];
};
void opna_ssg_reset(struct opna_ssg *ssg);