#732 added sound panning to the instruments

This commit is contained in:
nesbox 2018-09-17 11:22:01 +03:00
parent 68535f7b83
commit aa8d2e3856
5 changed files with 81 additions and 33 deletions

@ -1 +1 @@
Subproject commit e2d0f1a9760d75f241e70628f713777fef626ceb Subproject commit 746dd7ec6a6f4d142db9e01aaca9459d0154e9e9

View File

@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.9)
project(TIC-80 C) project(TIC-80 C)
message("Building for target : ${CMAKE_SYSTEM_NAME}") message("Building for target : ${CMAKE_SYSTEM_NAME}")
if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN) if(UNIX AND NOT APPLE AND NOT EMSCRIPTEN AND NOT ANDROID)
set(LINUX TRUE) set(LINUX TRUE)
endif() endif()

View File

@ -82,7 +82,12 @@ typedef struct
Clip clip; Clip clip;
tic_sound_register_data registers[TIC_SOUND_CHANNELS]; struct
{
tic_sound_register_data left[TIC_SOUND_CHANNELS];
tic_sound_register_data right[TIC_SOUND_CHANNELS];
} registers;
Channel channels[TIC_SOUND_CHANNELS]; Channel channels[TIC_SOUND_CHANNELS];
struct struct
{ {
@ -128,7 +133,12 @@ typedef struct
#endif #endif
}; };
blip_buffer_t* blip; struct
{
blip_buffer_t* left;
blip_buffer_t* right;
} blip;
s32 samplerate; s32 samplerate;
struct struct

View File

@ -120,7 +120,7 @@ static inline s32 getAmp(const tic_sound_register* reg, s32 amp)
return amp * MaxAmp * reg->volume / MAX_VOLUME; return amp * MaxAmp * reg->volume / MAX_VOLUME;
} }
static void runEnvelope(blip_buffer_t* blip, tic_sound_register* reg, tic_sound_register_data* data, s32 end_time ) static void runEnvelope(blip_buffer_t* blip, tic_sound_register* reg, tic_sound_register_data* data, s32 end_time, bool mute)
{ {
s32 period = freq2period(reg->freq * ENVELOPE_FREQ_SCALE); s32 period = freq2period(reg->freq * ENVELOPE_FREQ_SCALE);
@ -128,11 +128,11 @@ static void runEnvelope(blip_buffer_t* blip, tic_sound_register* reg, tic_sound_
{ {
data->phase = (data->phase + 1) % ENVELOPE_VALUES; data->phase = (data->phase + 1) % ENVELOPE_VALUES;
update_amp(blip, data, getAmp(reg, tic_tool_peek4(reg->waveform.data, data->phase))); update_amp(blip, data, mute ? 0 : getAmp(reg, tic_tool_peek4(reg->waveform.data, data->phase)));
} }
} }
static void runNoise(blip_buffer_t* blip, tic_sound_register* reg, tic_sound_register_data* data, s32 end_time ) static void runNoise(blip_buffer_t* blip, tic_sound_register* reg, tic_sound_register_data* data, s32 end_time, bool mute)
{ {
// phase is noise LFSR, which must never be zero // phase is noise LFSR, which must never be zero
if ( data->phase == 0 ) if ( data->phase == 0 )
@ -143,7 +143,7 @@ static void runNoise(blip_buffer_t* blip, tic_sound_register* reg, tic_sound_reg
for ( ; data->time < end_time; data->time += period ) for ( ; data->time < end_time; data->time += period )
{ {
data->phase = ((data->phase & 1) * (0b11 << 13)) ^ (data->phase >> 1); data->phase = ((data->phase & 1) * (0b11 << 13)) ^ (data->phase >> 1);
update_amp(blip, data, getAmp(reg, (data->phase & 1) ? MAX_VOLUME : 0)); update_amp(blip, data, mute ? 0 : getAmp(reg, (data->phase & 1) ? MAX_VOLUME : 0));
} }
} }
@ -479,7 +479,12 @@ static void soundClear(tic_mem* memory)
} }
{ {
tic_sound_register_data* data = &machine->state.registers[i]; tic_sound_register_data* data = &machine->state.registers.left[i];
memset(data, 0, sizeof(tic_sound_register_data));
}
{
tic_sound_register_data* data = &machine->state.registers.right[i];
memset(data, 0, sizeof(tic_sound_register_data)); memset(data, 0, sizeof(tic_sound_register_data));
} }
} }
@ -581,7 +586,8 @@ void tic_close(tic_mem* memory)
getWrenScriptConfig()->close(memory); getWrenScriptConfig()->close(memory);
#endif #endif
blip_delete(machine->blip); blip_delete(machine->blip.left);
blip_delete(machine->blip.right);
free(memory->samples.buffer); free(memory->samples.buffer);
free(machine); free(machine);
@ -1333,6 +1339,8 @@ static void api_tick_start(tic_mem* memory, const tic_sfx* sfxsrc, const tic_mus
for (s32 i = 0; i < TIC_SOUND_CHANNELS; ++i ) for (s32 i = 0; i < TIC_SOUND_CHANNELS; ++i )
memset(&memory->ram.registers[i], 0, sizeof(tic_sound_register)); memset(&memory->ram.registers[i], 0, sizeof(tic_sound_register));
memory->ram.panning.data = 0;
processMusic(memory); processMusic(memory);
for (s32 i = 0; i < TIC_SOUND_CHANNELS; ++i ) for (s32 i = 0; i < TIC_SOUND_CHANNELS; ++i )
@ -1373,6 +1381,26 @@ static void api_tick_start(tic_mem* memory, const tic_sfx* sfxsrc, const tic_mus
machine->state.drawhline = drawHLineDma; machine->state.drawhline = drawHLineDma;
} }
static void stereo_tick_end(tic_mem* memory, tic_sound_register_data* registers, blip_buffer_t* blip, u8 panningStart)
{
enum {EndTime = CLOCKRATE / TIC_FRAMERATE};
for (s32 i = 0; i < TIC_SOUND_CHANNELS; ++i )
{
bool mute = memory->ram.panning.data & (panningStart << (i << 1)) ? true : false;
tic_sound_register* reg = &memory->ram.registers[i];
tic_sound_register_data* data = registers + i;
isNoiseWaveform(&reg->waveform)
? runNoise(blip, reg, data, EndTime, mute)
: runEnvelope(blip, reg, data, EndTime, mute);
data->time -= EndTime;
}
blip_end_frame(blip, EndTime);
}
static void api_tick_end(tic_mem* memory) static void api_tick_end(tic_mem* memory)
{ {
tic_machine* machine = (tic_machine*)memory; tic_machine* machine = (tic_machine*)memory;
@ -1380,22 +1408,11 @@ static void api_tick_end(tic_mem* memory)
machine->state.gamepads.previous.data = machine->memory.ram.input.gamepads.data; machine->state.gamepads.previous.data = machine->memory.ram.input.gamepads.data;
machine->state.keyboard.previous.data = machine->memory.ram.input.keyboard.data; machine->state.keyboard.previous.data = machine->memory.ram.input.keyboard.data;
enum {EndTime = CLOCKRATE / TIC_FRAMERATE}; stereo_tick_end(memory, machine->state.registers.left, machine->blip.left, 1);
for (s32 i = 0; i < TIC_SOUND_CHANNELS; ++i ) stereo_tick_end(memory, machine->state.registers.right, machine->blip.right, 2);
{
tic_sound_register* reg = &memory->ram.registers[i];
tic_sound_register_data* data = &machine->state.registers[i];
isNoiseWaveform(&reg->waveform) blip_read_samples(machine->blip.left, machine->memory.samples.buffer, machine->samplerate / TIC_FRAMERATE, TIC_STEREO_CHANNLES);
? runNoise(machine->blip, reg, data, EndTime) blip_read_samples(machine->blip.right, machine->memory.samples.buffer + 1, machine->samplerate / TIC_FRAMERATE, TIC_STEREO_CHANNLES);
: runEnvelope(machine->blip, reg, data, EndTime);
data->time -= EndTime;
}
blip_end_frame(machine->blip, EndTime);
blip_read_samples(machine->blip, machine->memory.samples.buffer, machine->samplerate / TIC_FRAMERATE,
!memory->ram.sound_state.flag.stereo_mute_left, !memory->ram.sound_state.flag.stereo_mute_right);
machine->state.setpix = setPixelOvr; machine->state.setpix = setPixelOvr;
machine->state.getpix = getPixelOvr; machine->state.getpix = getPixelOvr;
@ -2034,9 +2051,11 @@ tic_mem* tic_create(s32 samplerate)
machine->memory.samples.size = samplerate * TIC_STEREO_CHANNLES / TIC_FRAMERATE * sizeof(s16); machine->memory.samples.size = samplerate * TIC_STEREO_CHANNLES / TIC_FRAMERATE * sizeof(s16);
machine->memory.samples.buffer = malloc(machine->memory.samples.size); machine->memory.samples.buffer = malloc(machine->memory.samples.size);
machine->blip = blip_new(samplerate / 10); machine->blip.left = blip_new(samplerate / 10);
machine->blip.right = blip_new(samplerate / 10);
blip_set_rates(machine->blip, CLOCKRATE, samplerate); blip_set_rates(machine->blip.left, CLOCKRATE, samplerate);
blip_set_rates(machine->blip.right, CLOCKRATE, samplerate);
machine->memory.api.reset(&machine->memory); machine->memory.api.reset(&machine->memory);

View File

@ -186,8 +186,8 @@ typedef struct
s8 speed:3; s8 speed:3;
u8 reverse:1; // arpeggio reverse u8 reverse:1; // arpeggio reverse
u8 note:4; u8 note:4;
u8 chain:1; u8 panning:2; // 00 - center, 01 - left, 10 - right, 11 - mute
u8 temp:3; u8 temp:2;
}; };
union union
@ -287,13 +287,31 @@ typedef struct
{ {
u8 music_loop:1; u8 music_loop:1;
u8 music_state:2; // enum tic_music_state u8 music_state:2; // enum tic_music_state
u8 unknown:1; u8 unknown:5;
u8 stereo_mute_left:1;
u8 stereo_mute_right:1;
} flag; } flag;
} tic_sound_state; } tic_sound_state;
typedef union
{
struct
{
u8 l1:1;
u8 r1:1;
u8 l2:1;
u8 r2:1;
u8 l3:1;
u8 r3:1;
u8 l4:1;
u8 r4:1;
};
u8 data;
} tic_sound_panning;
typedef struct typedef struct
{ {
struct struct
@ -432,7 +450,8 @@ typedef union
tic_tiles sprites; tic_tiles sprites;
tic_map map; tic_map map;
tic80_input input; tic80_input input;
u8 unknown[16]; u8 unknown[15];
tic_sound_panning panning;
tic_sound_register registers[TIC_SOUND_CHANNELS]; tic_sound_register registers[TIC_SOUND_CHANNELS];
tic_sfx sfx; tic_sfx sfx;
tic_music music; tic_music music;