Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions libntxm/arm7/source/fifocommand7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ static void RecvCommandSetSong(SetSongCommand *c) {
ntxm7->setSong((Song*)c->ptr);
}

static void RecvCommandSetCursorPosPtr(SetCursorPosPtrCommand *c) {
ntxm7->setCursorPosPtr(c->cursorptr);
}

static void RecvCommandStartPlay(StartPlayCommand *c) {
ntxm7->play(c->loop, c->potpos, c->row);
}
Expand Down Expand Up @@ -203,6 +207,9 @@ void CommandRecvHandler(int bytes, void *user_data) {
case STOP_PLAY:
RecvCommandStopPlay(&command.stopPlay);
break;
case SET_CURSORPOS_PTR:
RecvCommandSetCursorPosPtr(&command.setCursorPosPtr);
break;
case PLAY_INST:
RecvCommandPlayInst(&command.playInst);
break;
Expand Down
4 changes: 4 additions & 0 deletions libntxm/arm7/source/ntxm7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,7 @@ void NTXM7::setPatternLoop(bool loopstate)
{
player->setPatternLoop(loopstate);
}

void NTXM7::setCursorPosPtr(SampleCursor *cursorptr) {
player->setCursorPosPtr(cursorptr);
}
62 changes: 55 additions & 7 deletions libntxm/arm7/source/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ extern bool ntxm_recording;
/* ===================== PUBLIC ===================== */

Player::Player(void (*_externalTimerHandler)(void))
:song(0), externalTimerHandler(_externalTimerHandler)
:song(0), playingNotes(0), externalTimerHandler(_externalTimerHandler)
{
initState();

Expand Down Expand Up @@ -121,6 +121,9 @@ void Player::play(u8 potpos, u16 row, bool loop)

void Player::stop(void)
{
for (int i = 0; i < 16; ++i)
clearPlayingData(i);

if (!state.playing)
return;

Expand Down Expand Up @@ -212,6 +215,18 @@ void Player::playNote(u8 note, u8 volume, u8 channel, u8 instidx)
if (effect == EFFECT_SAMPLE_OFFSET)
offs = param;

if (smp->getLoop() != 0)
offs = ntxm_clamp(offs, 0, smp->getLoopStart());

playingNotes[channel] =
{
.playbackpos = ((u64)((FT_OFFSET_SCALAR * offs * (smp->is16bit() ? 2 : 1)))) << 31, // we also need to divide by two, so lshift 31 instead of 32
.playbackfreq = smp->getPlaybackFreq(note),
.active = true,
.looprev = false,
.instidx = instidx,
.smpidx = inst->getNoteSample(note),
};
inst->play(note, volume, channel, offs);
}

Expand Down Expand Up @@ -249,6 +264,8 @@ void Player::stopAllNotes(u8 note, u8 instidx)
// Stop playback on a channel
void Player::stopChannel(u8 channel)
{
clearPlayingData(channel);

// Stop single sample if it's played on this channel
if((state.playing_single_sample == true) && (state.single_sample_channel == channel))
{
Expand Down Expand Up @@ -444,6 +461,9 @@ void Player::playTimerHandler(void)
chnvol = (u8)((state.channel_volume[channel]) * ((state.channel_env_vol[channel] << 8) / 0x210) / 0x1f);
}

if (state.channel_env_vol[channel] < 0x01)
clearPlayingData(channel);

SCHANNEL_VOL(channel) = SOUND_VOL(chnvol);

if(state.channel_active[channel] == CHANNEL_TO_BE_DISABLED)
Expand Down Expand Up @@ -951,22 +971,24 @@ void Player::handleTickEffects(void)
if (inst == NULL)
continue;

u32 newfreq = 0;
switch(state.row_ticks % 3)
{
case(0):
inst->bendNote(state.channel_note[channel] + 0,
newfreq = inst->bendNote(state.channel_note[channel] + 0,
state.channel_note[channel], 0, channel);
break;
case(1):
inst->bendNote(state.channel_note[channel] + halftone1,
newfreq = inst->bendNote(state.channel_note[channel] + halftone1,
state.channel_note[channel], 0, channel);
break;
case(2):
inst->bendNote(state.channel_note[channel] + halftone2,
newfreq = inst->bendNote(state.channel_note[channel] + halftone2,
state.channel_note[channel], 0, channel);
break;
}

if (newfreq) playingNotes[channel].playbackfreq = newfreq;
break;
}

Expand All @@ -980,7 +1002,9 @@ void Player::handleTickEffects(void)
{
state.channel_porta_accumulator[channel] = (19968 << PORTA_PRECISION);
}
inst->bendNoteDirect(state.channel_note[channel], state.channel_porta_accumulator[channel] >> PORTA_PRECISION, channel);

u32 bendfreq = inst->bendNoteDirect(state.channel_note[channel], state.channel_porta_accumulator[channel] >> PORTA_PRECISION, channel);
if (bendfreq) playingNotes[channel].playbackfreq = bendfreq;
break;
}

Expand All @@ -994,7 +1018,9 @@ void Player::handleTickEffects(void)
{
state.channel_porta_accumulator[channel] = 0;
}
inst->bendNoteDirect(state.channel_note[channel], state.channel_porta_accumulator[channel] >> PORTA_PRECISION, channel);

u32 bendfreq = inst->bendNoteDirect(state.channel_note[channel], state.channel_porta_accumulator[channel] >> PORTA_PRECISION, channel);
if (bendfreq) playingNotes[channel].playbackfreq = bendfreq;
break;
}

Expand Down Expand Up @@ -1027,7 +1053,9 @@ void Player::handleTickEffects(void)
{
state.channel_porta_accumulator[channel] = (19968 << PORTA_PRECISION);
}
inst->bendNoteDirect(state.channel_note[channel], state.channel_porta_accumulator[channel] >> PORTA_PRECISION, channel);

u32 bendfreq = inst->bendNoteDirect(state.channel_note[channel], state.channel_porta_accumulator[channel] >> PORTA_PRECISION, channel);
if (bendfreq) playingNotes[channel].playbackfreq = bendfreq;
break;
}

Expand Down Expand Up @@ -1308,6 +1336,8 @@ void Player::handleFade(u32 passed_time)
// If we reached 0 ms, disable the fader (and the channel)
if(state.channel_fade_ms[channel] == 0)
{
clearPlayingData(channel);

state.channel_fade_active[channel] = 0;

state.channel_volume[channel] = state.channel_fade_target_volume[channel];
Expand Down Expand Up @@ -1377,3 +1407,21 @@ bool Player::calcNextPos(u16 *nextrow, u8 *nextpotpos) // Calculate next row and

return false;
}

void Player::clearPlayingData(u8 chn)
{
playingNotes[chn] =
{
.playbackpos = 0,
.playbackfreq = 0,
.active = 0,
.looprev = 0,
.instidx = 255,
.smpidx = 0,
};
}

void Player::setCursorPosPtr(SampleCursor *cpos)
{
playingNotes = cpos;
}
11 changes: 11 additions & 0 deletions libntxm/arm9/source/fifocommand9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,17 @@ void CommandStopPlay(void) {
fifoSendDatamsg(FIFO_NTXM, sizeof(command), (u8*)&command);
}

void CommandSetCursorPosPtr(SampleCursor *cptr)
{
NTXMFifoMessage command;
command.commandType = SET_CURSORPOS_PTR;

SetCursorPosPtrCommand* c = &command.setCursorPosPtr;

c->cursorptr = cptr;

fifoSendDatamsg(FIFO_NTXM, sizeof(command), (u8*)&command);
}
void CommandPlayInst(u8 inst, u8 note, u8 volume, u8 channel)
{
NTXMFifoMessage command;
Expand Down
17 changes: 10 additions & 7 deletions libntxm/common/source/instrument.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,30 +161,33 @@ void Instrument::play(u8 _note, u8 _volume, u8 _channel /* effects here */, u8 o
}
}

void Instrument::bendNote(u8 _note, u8 _basenote, s16 _finetune, u8 _channel)
u32 Instrument::bendNote(u8 _note, u8 _basenote, s16 _finetune, u8 _channel)
{
if(_note > MAX_NOTE)
return;
return NULL;

switch(type) {
case INST_SAMPLE:
if(n_samples > 0)
samples[note_samples[_note]]->bendNote(_note, _basenote, _finetune, _channel);
return samples[note_samples[_note]]->bendNote(_note, _basenote, _finetune, _channel);
break;
}

return NULL;
}

void Instrument::bendNoteDirect(u8 _note, s16 _fine_step, u8 _channel)
u32 Instrument::bendNoteDirect(u8 _note, s16 _fine_step, u8 _channel)
{
if(_fine_step > 19968) // 19968 is the highest intermediary pitch calculation
return; // before converted to an index value for lookup table

return NULL; // before converted to an index value for lookup table
switch(type) {
case INST_SAMPLE:
if(n_samples > 0)
samples[note_samples[_note]]->bendNoteDirect(_fine_step, _channel);
return samples[note_samples[_note]]->bendNoteDirect(_fine_step, _channel);
break;
}

return NULL;
}

#endif
Expand Down
23 changes: 16 additions & 7 deletions libntxm/common/source/sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ inline u32 linear_freq_table_lookup(u32 note)
Sample::Sample(void *_sound_data, u32 _n_samples, u16 _sampling_frequency, bool _is_16_bit,
u8 _loop, u8 _volume)
:pingpong_data(0), n_samples(_n_samples), is_16_bit(_is_16_bit), loop(_loop),
loop_start(0), loop_length(0), volume(_volume), panning(128), base_panning(128)
loop_start(0), loop_length(0), volume(_volume), panning(128), base_panning(128),
sampling_frequency(_sampling_frequency)
{
sound_data = _sound_data;

Expand Down Expand Up @@ -131,7 +132,7 @@ Sample::Sample(const char *filename, u8 _loop, bool *_success)
sound_data = wav.getAudioData();

calcRelnoteAndFinetune( wav.getSamplingRate() );

sampling_frequency = wav.getSamplingRate();
u8 bit_per_sample = wav.getBitPerSample();

if(bit_per_sample == 16)
Expand Down Expand Up @@ -282,27 +283,31 @@ void Sample::play(u8 note, u8 volume_, u8 channel, u8 offs)
SOUND_VOL(smpvolume);
}

void Sample::bendNote(u8 note, u8 basenote, s16 _finetune, u8 channel)
u32 Sample::bendNote(u8 note, u8 basenote, s16 _finetune, u8 channel)
{
// Add 48 to the note, because otherwise absolute_note can get negative.
// (The minimum value of relative note is -48)
u8 absolute_note = note + 48;
u8 realnote = (absolute_note+rel_note);
_finetune += finetune; //Need to offset by sample's finetune
SCHANNEL_TIMER(channel) = SOUND_FREQ((int)LOOKUP_FREQ(realnote,_finetune));
u32 bendfreq = LOOKUP_FREQ(realnote,_finetune);
SCHANNEL_TIMER(channel) = SOUND_FREQ((int)bendfreq);
return bendfreq;
}

void Sample::bendNoteDirect(s16 fine_step, u8 channel)
u32 Sample::bendNoteDirect(s16 fine_step, u8 channel)
{
CommandDbgOut("finestep: 0x%x channel: 0x%x\n", fine_step, channel);
SCHANNEL_TIMER(channel) = SOUND_FREQ((int)GET_FREQ_DIRECT(fine_step));
u32 bendfreq = GET_FREQ_DIRECT(fine_step);
SCHANNEL_TIMER(channel) = SOUND_FREQ((int)bendfreq);
return bendfreq;
}

#endif

u32 Sample::calcPlayLength(u8 note)
{
u32 samples_per_second = LOOKUP_FREQ(48+note+rel_note,finetune);
u32 samples_per_second = getPlaybackFreq(note);
if (samples_per_second == 0) return 0;
return n_samples * 1000 / samples_per_second;
}
Expand Down Expand Up @@ -337,6 +342,10 @@ u32 Sample::getNSamples(void)
return n_samples;
}

u32 Sample::getPlaybackFreq(u8 note_) {
return LOOKUP_FREQ(48+note_+rel_note,finetune);
}

void *Sample::getData(void)
{
return sound_data;
Expand Down
9 changes: 8 additions & 1 deletion libntxm/include/ntxm/fifocommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ typedef enum {
MIC_OFF,
PATTERN_LOOP,
SAMPLE_FINISH,
SET_STEREO_OUTPUT
SET_STEREO_OUTPUT,
SET_CURSORPOS_PTR
} NTXMFifoMessageType;

struct PlaySampleCommand
Expand Down Expand Up @@ -86,6 +87,10 @@ struct UpdatePotPosCommand {
u16 potpos;
};

struct SetCursorPosPtrCommand {
SampleCursor *cursorptr;
};

struct PlayInstCommand {
u8 inst;
u8 note;
Expand Down Expand Up @@ -144,6 +149,7 @@ typedef struct NTXMFifoMessage {
StopNoteAutoCommand stopNoteAuto;
PatternLoopCommand ptnLoop;
SetStereoOutputCommand setStereoOutput;
SetCursorPosPtrCommand setCursorPosPtr;
};
} NTXMFifoMessage;

Expand All @@ -160,6 +166,7 @@ void CommandSetSong(void *song);
void CommandStartPlay(u8 potpos, u16 row, bool loop);
void CommandStopPlay(void);
void CommandSetDebugStrPtr(char **arm7debugstrs, u16 debugstrsize, u8 n_debugbufs);
void CommandSetCursorPosPtr(SampleCursor *cursorpos);
void CommandPlayInst(u8 inst, u8 note, u8 volume, u8 channel);
void CommandStopInst(u8 channel);
void CommandStopMatchingInst(u8 inst, u8 note);
Expand Down
4 changes: 2 additions & 2 deletions libntxm/include/ntxm/instrument.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ class Instrument
void setSample(u8 idx, Sample *sample);
Sample *getSampleForNote(u8 _note);
void play(u8 _note, u8 _volume, u8 _channel, u8 offs = 0);
void bendNote(u8 _note, u8 _basenote, s16 _finetune, u8 _channel);
void bendNoteDirect(u8 _note, s16 _fine_step, u8 _channel);
u32 bendNote(u8 _note, u8 _basenote, s16 _finetune, u8 _channel);
u32 bendNoteDirect(u8 _note, s16 _fine_step, u8 _channel);
void setNoteSample(u16 note, u8 sample_id);
u8 getNoteSample(u16 note);
void setVolEnvEnabled(bool is_enabled);
Expand Down
3 changes: 3 additions & 0 deletions libntxm/include/ntxm/ntxm7.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ class NTXM7

// Set a pattern to looping
void setPatternLoop(bool loopstate);

// Set the memory address of where to write the cursor position to for arm9
void setCursorPosPtr(SampleCursor *cursorptr);

private:
Player *player;
Expand Down
6 changes: 5 additions & 1 deletion libntxm/include/ntxm/player.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ class Player {

void playTimerHandler(void);
void stopSampleFadeoutTimerHandler(void);

void setCursorPosPtr(SampleCursor *cursorptr);
private:

void startPlayTimer(void);
Expand All @@ -201,10 +201,14 @@ class Player {

bool calcNextPos(u16 *nextrow, u8 *nextpotpos); // Calculate next row and pot position

void clearPlayingData(u8 chn);

Song *song;
PlayerState state;
EffectState effstate;

SampleCursor *playingNotes;

void (*externalTimerHandler)(void);
void (*onRow)(u16);
void (*onPatternChange)(u8);
Expand Down
Loading