Commit f51f7a47 authored by Erik Faye-Lund's avatar Erik Faye-Lund
Browse files

fixed the main player-logic a bit

git-svn-id: https://pimpmobile.svn.sourceforge.net/svnroot/pimpmobile/trunk@77 3d5ecaf0-f903-0410-b953-c2c1a4d75763
parent 7097de94
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#define CHANNELS 32 #define CHANNELS 32
/* check the sample-rate calculator at http://www.pineight.com/gba/samplerates/ for more glitch-free samplerates */ /* check the sample-rate calculator at http://www.pineight.com/gba/samplerates/ for more glitch-free samplerates */
#define SAMPLERATE (18157) #define SAMPLERATE (18157 * 2)
/* only 130 bytes big, quite damn pleasing results */ /* only 130 bytes big, quite damn pleasing results */
#define AMIGA_DELTA_LUT_LOG_SIZE 7 #define AMIGA_DELTA_LUT_LOG_SIZE 7
......
...@@ -36,22 +36,6 @@ typedef struct ...@@ -36,22 +36,6 @@ typedef struct
} pimp_sample_t; } pimp_sample_t;
typedef struct
{
s32 period;
s32 final_period; /* signed so we can check for underfow */
s32 porta_target;
u16 porta_speed;
s8 volume_slide_speed;
s8 volume;
u8 pan;
u8 note;
u8 effect;
u8 effect_param;
} pimp_channel_state_t;
typedef enum typedef enum
{ {
EFF_NONE = 0x00, EFF_NONE = 0x00,
...@@ -252,4 +236,24 @@ typedef struct ...@@ -252,4 +236,24 @@ typedef struct
u8 channel_count; u8 channel_count;
} pimp_module_t; } pimp_module_t;
typedef struct
{
s32 period;
s32 final_period; /* signed so we can check for underfow */
s32 porta_target;
u16 porta_speed;
s8 volume_slide_speed;
s8 volume;
u8 pan;
pimp_instrument_t *instrument;
pimp_sample_t *sample;
u8 note;
u8 effect;
u8 effect_param;
} pimp_channel_state_t;
#endif /* INTERNAL_H */ #endif /* INTERNAL_H */
...@@ -39,9 +39,9 @@ unsigned get_linear_period(int note, int fine_tune) ...@@ -39,9 +39,9 @@ unsigned get_linear_period(int note, int fine_tune)
assert(fine_tune >= -8); assert(fine_tune >= -8);
assert(fine_tune < 8); assert(fine_tune < 8);
int xm_note = note - (12 * 1); // we extended our note-range with one octave. int xm_note = note - (12 * 1) - 1; // we extended our note-range with one octave.
return 10 * 12 * 16 * 4 - xm_note * 16 * 4 - fine_tune / 2; return (10 * 12 * 16 * 4 - xm_note * 16 * 4 - fine_tune / 2);
// return 10 * 12 * 16 * 4 - note * 16 * 4 - fine_tune / 2; // return 10 * 12 * 16 * 4 - note * 16 * 4 - fine_tune / 2;
} }
......
...@@ -152,7 +152,6 @@ static inline void mix_channel(channel_t &chan, s32 *target, size_t samples) ...@@ -152,7 +152,6 @@ static inline void mix_channel(channel_t &chan, s32 *target, size_t samples)
while (samples > 0 && detect_loop_event(chan, samples) == true) while (samples > 0 && detect_loop_event(chan, samples) == true)
{ {
DEBUG_COLOR(31, 31, 31);
do do
{ {
assert((chan.sample_cursor >> 12) < chan.sample_length); assert((chan.sample_cursor >> 12) < chan.sample_length);
...@@ -176,18 +175,12 @@ static inline void mix_channel(channel_t &chan, s32 *target, size_t samples) ...@@ -176,18 +175,12 @@ static inline void mix_channel(channel_t &chan, s32 *target, size_t samples)
} }
chan.sample_data = 0; chan.sample_data = 0;
return; return;
} }
} }
DEBUG_COLOR(31, 0, 31);
timing_start();
assert(chan.sample_data != 0); assert(chan.sample_data != 0);
chan.sample_cursor = mix_samples(target, samples, chan.sample_data, chan.volume, chan.sample_cursor, chan.sample_cursor_delta); chan.sample_cursor = mix_samples(target, samples, chan.sample_data, chan.volume, chan.sample_cursor, chan.sample_cursor_delta);
timing_end();
DEBUG_COLOR(31, 0, 0);
} }
void mixer::reset() void mixer::reset()
...@@ -206,8 +199,6 @@ void mixer::mix(s8 *target, size_t samples) ...@@ -206,8 +199,6 @@ void mixer::mix(s8 *target, size_t samples)
{ {
assert(samples > 0); assert(samples > 0);
DEBUG_COLOR(0, 31, 31);
// zero out the sample-buffer // zero out the sample-buffer
u32 zero = 0; u32 zero = 0;
CpuFastSet(&zero, sound_mix_buffer, DMA_SRC_FIXED | (samples)); CpuFastSet(&zero, sound_mix_buffer, DMA_SRC_FIXED | (samples));
...@@ -219,7 +210,6 @@ void mixer::mix(s8 *target, size_t samples) ...@@ -219,7 +210,6 @@ void mixer::mix(s8 *target, size_t samples)
if (0 != chan.sample_data && 0 != chan.sample_cursor_delta) mix_channel(chan, sound_mix_buffer, samples); if (0 != chan.sample_data && 0 != chan.sample_cursor_delta) mix_channel(chan, sound_mix_buffer, samples);
} }
dc_offs >>= 8; dc_offs >>= 8;
DEBUG_COLOR(0, 31, 0);
register s32 *src = sound_mix_buffer; register s32 *src = sound_mix_buffer;
register s8 *dst = target; register s8 *dst = target;
...@@ -264,5 +254,4 @@ void mixer::mix(s8 *target, size_t samples) ...@@ -264,5 +254,4 @@ void mixer::mix(s8 *target, size_t samples)
while (s--); while (s--);
} }
#undef ITERATION #undef ITERATION
DEBUG_COLOR(0, 0, 0);
} }
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <assert.h> #include <assert.h>
#include "mixer.h" #include "mixer.h"
#include "debug.h"
#include <gba_base.h> #include <gba_base.h>
#include <gba_video.h>
int profile_counter = 0;
static u32 mix_simple(s32 *target, u32 samples, const u8 *sample_data, u32 vol, u32 sample_cursor, s32 sample_cursor_delta) static u32 mix_simple(s32 *target, u32 samples, const u8 *sample_data, u32 vol, u32 sample_cursor, s32 sample_cursor_delta)
{ {
...@@ -10,7 +14,6 @@ static u32 mix_simple(s32 *target, u32 samples, const u8 *sample_data, u32 vol, ...@@ -10,7 +14,6 @@ static u32 mix_simple(s32 *target, u32 samples, const u8 *sample_data, u32 vol,
assert(sample_data != 0); assert(sample_data != 0);
assert((samples & 7) == 0); assert((samples & 7) == 0);
assert(samples != 0); assert(samples != 0);
asm( asm(
"\ "\
b .Ldataskip%= \n\ b .Ldataskip%= \n\
...@@ -68,7 +71,6 @@ static u32 mix_simple(s32 *target, u32 samples, const u8 *sample_data, u32 vol, ...@@ -68,7 +71,6 @@ static u32 mix_simple(s32 *target, u32 samples, const u8 *sample_data, u32 vol,
[vol] "r"(vol) [vol] "r"(vol)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "sp", "1", "2", "4", "cc" : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "sp", "1", "2", "4", "cc"
); );
return sample_cursor; return sample_cursor;
} }
...@@ -81,7 +83,7 @@ static u32 mix_bresenham(s32 *target, u32 samples, const u8 *sample_data, u32 vo ...@@ -81,7 +83,7 @@ static u32 mix_bresenham(s32 *target, u32 samples, const u8 *sample_data, u32 vo
assert(sample_data != 0); assert(sample_data != 0);
assert((samples & 7) == 0); assert((samples & 7) == 0);
assert(samples != 0); assert(samples != 0);
asm( asm(
"\ "\
b .Ldataskip%= \n\ b .Ldataskip%= \n\
...@@ -150,7 +152,6 @@ static u32 mix_bresenham(s32 *target, u32 samples, const u8 *sample_data, u32 vo ...@@ -150,7 +152,6 @@ static u32 mix_bresenham(s32 *target, u32 samples, const u8 *sample_data, u32 vo
[vol] "r"(vol) [vol] "r"(vol)
: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "sp", "cc" : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "sp", "cc"
); );
return ((sample_data - old_sample_data - 1) << 12) + (sample_cursor >> 20); return ((sample_data - old_sample_data - 1) << 12) + (sample_cursor >> 20);
} }
...@@ -173,12 +174,14 @@ u32 mixer::mix_samples(s32 *target, u32 samples, const u8 *sample_data, u32 vol, ...@@ -173,12 +174,14 @@ u32 mixer::mix_samples(s32 *target, u32 samples, const u8 *sample_data, u32 vol,
// return mix_simple(target, samples, sample_data, vol, sample_cursor, sample_cursor_delta); // return mix_simple(target, samples, sample_data, vol, sample_cursor, sample_cursor_delta);
/* decide what innerloop to take */ /* decide what innerloop to take */
if (sample_cursor_delta > 0 && sample_cursor_delta < u32((1 << 12) * 0.95)) if (sample_cursor_delta > 0 && sample_cursor_delta < (1 << 12))
{ {
return mix_bresenham(target, samples, sample_data, vol, sample_cursor, sample_cursor_delta); u32 ret = mix_bresenham(target, samples, sample_data, vol, sample_cursor, sample_cursor_delta);
return ret;
} }
else else
{ {
return mix_simple(target, samples, sample_data, vol, sample_cursor, sample_cursor_delta); u32 ret = mix_simple(target, samples, sample_data, vol, sample_cursor, sample_cursor_delta);
return ret;
} }
} }
...@@ -29,6 +29,12 @@ ...@@ -29,6 +29,12 @@
#include "math.h" #include "math.h"
#include "debug.h" #include "debug.h"
#define PRINT_PATTERNS
static s8 sound_buffers[2][SOUND_BUFFER_SIZE] IWRAM_DATA; static s8 sound_buffers[2][SOUND_BUFFER_SIZE] IWRAM_DATA;
static u32 sound_buffer_index = 0; static u32 sound_buffer_index = 0;
...@@ -41,6 +47,9 @@ static u32 curr_order = 0; ...@@ -41,6 +47,9 @@ static u32 curr_order = 0;
static u32 curr_bpm = 125; static u32 curr_bpm = 125;
static u32 curr_tempo = 5; static u32 curr_tempo = 5;
static u32 curr_tick = 0; static u32 curr_tick = 0;
static s32 global_volume = 2 << 8; /* 24.8 fixed point */
static pimp_pattern_t *curr_pattern = 0; static pimp_pattern_t *curr_pattern = 0;
static const unsigned char *pimp_sample_bank; static const unsigned char *pimp_sample_bank;
...@@ -85,6 +94,7 @@ static pimp_sample_t *get_sample(const pimp_module_t *mod, pimp_instrument_t *in ...@@ -85,6 +94,7 @@ static pimp_sample_t *get_sample(const pimp_module_t *mod, pimp_instrument_t *in
} }
#ifdef PRINT_PATTERNS
void print_pattern_entry(const pimp_pattern_entry_t &pe) void print_pattern_entry(const pimp_pattern_entry_t &pe)
{ {
if (pe.note != 0) if (pe.note != 0)
...@@ -98,6 +108,7 @@ void print_pattern_entry(const pimp_pattern_entry_t &pe) ...@@ -98,6 +108,7 @@ void print_pattern_entry(const pimp_pattern_entry_t &pe)
} }
else iprintf("--- "); else iprintf("--- ");
// iprintf("%02X ", pe.volume_command); // iprintf("%02X ", pe.volume_command);
iprintf("%02X ", pe.effect_byte);
// iprintf("%02X %02X %X%02X\t", pe.instrument, pe.volume_command, pe.effect_byte, pe.effect_parameter); // iprintf("%02X %02X %X%02X\t", pe.instrument, pe.volume_command, pe.effect_byte, pe.effect_parameter);
} }
...@@ -117,6 +128,7 @@ void print_pattern(const pimp_module_t *mod, pimp_pattern_t *pat) ...@@ -117,6 +128,7 @@ void print_pattern(const pimp_module_t *mod, pimp_pattern_t *pat)
iprintf("\n"); iprintf("\n");
} }
} }
#endif
static pimp_callback callback = 0; static pimp_callback callback = 0;
extern "C" void pimp_set_callback(pimp_callback in_callback) extern "C" void pimp_set_callback(pimp_callback in_callback)
...@@ -214,7 +226,9 @@ void update_row() ...@@ -214,7 +226,9 @@ void update_row()
const pimp_pattern_entry_t *note = &get_pattern_data(mod, curr_pattern)[curr_row * mod->channel_count + c]; const pimp_pattern_entry_t *note = &get_pattern_data(mod, curr_pattern)[curr_row * mod->channel_count + c];
#ifdef PRINT_PATTERNS
print_pattern_entry(*note); print_pattern_entry(*note);
#endif
chan.effect = note->effect_byte; chan.effect = note->effect_byte;
chan.effect_param = note->effect_parameter; chan.effect_param = note->effect_parameter;
...@@ -222,41 +236,43 @@ void update_row() ...@@ -222,41 +236,43 @@ void update_row()
bool period_dirty = false; bool period_dirty = false;
bool volume_dirty = false; bool volume_dirty = false;
// NOTE ON ! if (note->instrument > 0)
if (note->instrument > 0 && chan.effect != EFF_PORTA_NOTE) {
chan.instrument = get_instrument(mod, note->instrument - 1);
chan.sample = get_sample(mod, chan.instrument, chan.instrument->sample_map[note->note]);
chan.volume = chan.sample->volume;
volume_dirty = true;
}
if (chan.instrument != 0 && note->note > 0 && chan.effect != EFF_PORTA_NOTE)
{ {
pimp_instrument_t *instr = get_instrument(mod, note->instrument - 1); chan.sample = get_sample(mod, chan.instrument, chan.instrument->sample_map[note->note]);
pimp_sample_t *samp = get_sample(mod, instr, instr->sample_map[note->note]); mc.sample_cursor = 0;
mc.sample_data = pimp_sample_bank + chan.sample->data_ptr;
mc.sample_length = chan.sample->length;
mc.loop_type = (mixer::loop_type_t)chan.sample->loop_type;
mc.loop_start = chan.sample->loop_start;
mc.loop_end = chan.sample->loop_start + chan.sample->loop_length;
int period;
if (mod->flags & FLAG_LINEAR_PERIODS) if (mod->flags & FLAG_LINEAR_PERIODS)
{ {
period = get_linear_period(note->note, samp->fine_tune); chan.period = get_linear_period(((s32)note->note) + chan.sample->rel_note, chan.sample->fine_tune);
} }
else else
{ {
period = get_amiga_period(note->note, samp->fine_tune); chan.period = get_amiga_period(((s32)note->note) + chan.sample->rel_note, chan.sample->fine_tune);
} }
chan.final_period = chan.period;
chan.period = chan.final_period = period;
period_dirty = true; period_dirty = true;
mc.sample_cursor = 0;
mc.sample_data = pimp_sample_bank + samp->data_ptr;
mc.sample_length = samp->length;
mc.loop_type = (mixer::loop_type_t)samp->loop_type;
mc.loop_start = samp->loop_start;
mc.loop_end = samp->loop_start + samp->loop_length;
} }
if (note->instrument > 0) if (note->instrument > 0)
{ {
pimp_instrument_t *instr = get_instrument(mod, note->instrument - 1); chan.volume = chan.sample->volume;
pimp_sample_t *samp = get_sample(mod, instr, instr->sample_map[note->note]);
chan.volume = samp->volume;
volume_dirty = true; volume_dirty = true;
} }
/* todo: switch here instead */ /* todo: switch here instead */
if (note->volume_command >= 0x10 && note->volume_command < 0x50) if (note->volume_command >= 0x10 && note->volume_command < 0x50)
{ {
...@@ -279,7 +295,8 @@ void update_row() ...@@ -279,7 +295,8 @@ void update_row()
case EFF_PORTA_NOTE: case EFF_PORTA_NOTE:
if (note->note > 0) if (note->note > 0)
{ {
if (mod->flags & FLAG_LINEAR_PERIODS) chan.porta_target = get_linear_period(note->note, 0); // no fine tune or relative note here, boooy
if (mod->flags & FLAG_LINEAR_PERIODS) chan.porta_target = get_linear_period(note->note + chan.sample->rel_note, 0);
else chan.porta_target = get_amiga_period(note->note, 0); else chan.porta_target = get_amiga_period(note->note, 0);
/* clamp porta-target period (should not be done for S3M) */ /* clamp porta-target period (should not be done for S3M) */
...@@ -340,8 +357,8 @@ void update_row() ...@@ -340,8 +357,8 @@ void update_row()
chan.note = note->note; chan.note = note->note;
break; break;
*/ */
default: // default:
iprintf("eek E%X\n", chan.effect_param >> 4); // iprintf("eek E%X\n", chan.effect_param >> 4);
} }
break; break;
...@@ -370,8 +387,8 @@ void update_row() ...@@ -370,8 +387,8 @@ void update_row()
case EFF_SET_BPM: break; case EFF_SET_BPM: break;
*/ */
default: // default:
iprintf("eek %02X!\n", chan.effect); // iprintf("eek %02X!\n", chan.effect);
// assert(0); // assert(0);
} }
...@@ -389,12 +406,14 @@ void update_row() ...@@ -389,12 +406,14 @@ void update_row()
if (volume_dirty) if (volume_dirty)
{ {
mc.volume = chan.volume * 2; mc.volume = (chan.volume * global_volume) >> 8;
} }
} }
#ifdef PRINT_PATTERNS
iprintf("\n"); iprintf("\n");
#endif
curr_tick = 0; curr_tick = 0;
curr_row++; curr_row++;
if (curr_row == curr_pattern->row_count) if (curr_row == curr_pattern->row_count)
...@@ -509,7 +528,7 @@ static void update_tick() ...@@ -509,7 +528,7 @@ static void update_tick()
if (volume_dirty) if (volume_dirty)
{ {
mc.volume = chan.volume * 2; mc.volume = (chan.volume * global_volume) >> 8;
} }
} }
curr_tick++; curr_tick++;
...@@ -524,8 +543,6 @@ static void update_tick() ...@@ -524,8 +543,6 @@ static void update_tick()
extern "C" void pimp_frame() extern "C" void pimp_frame()
{ {
DEBUG_COLOR(31, 31, 31);
u32 samples_left = SOUND_BUFFER_SIZE; u32 samples_left = SOUND_BUFFER_SIZE;
s8 *buf = sound_buffers[sound_buffer_index]; s8 *buf = sound_buffers[sound_buffer_index];
...@@ -533,25 +550,18 @@ extern "C" void pimp_frame() ...@@ -533,25 +550,18 @@ extern "C" void pimp_frame()
while (true) while (true)
{ {
int samples_to_mix = MIN(remainder, samples_left); int samples_to_mix = MIN(remainder, samples_left);
if (samples_to_mix != 0) mixer::mix(buf, samples_to_mix); if (samples_to_mix != 0) mixer::mix(buf, samples_to_mix);
DEBUG_COLOR(31, 31, 31);
buf += samples_to_mix; buf += samples_to_mix;
samples_left -= samples_to_mix; samples_left -= samples_to_mix;
remainder -= samples_to_mix; remainder -= samples_to_mix;
if (!samples_left) break; if (!samples_left) break;
DEBUG_COLOR(0, 0, 0);
update_tick(); update_tick();
DEBUG_COLOR(31, 31, 31);
// printf("%d %d %d %d\n", mod->bpm, curr_row, curr_order, curr_tick);
// fixed point tick length // fixed point tick length
curr_tick_len += tick_len; curr_tick_len += tick_len;
remainder = curr_tick_len >> 8; remainder = curr_tick_len >> 8;
curr_tick_len -= (curr_tick_len >> 8) << 8; curr_tick_len -= (curr_tick_len >> 8) << 8;
} }
DEBUG_COLOR(0, 0, 0);
} }
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment