this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

PCM sound channel (#2488)

* PCM proof of concept

* build fix

* better impl

* better impl

* tiny fixes

authored by

Vadim Grigoruk and committed by
GitHub
0952e911 6e849134

+65 -34
+1
src/core/core.c
··· 305 305 } 306 306 307 307 memset(&memory->ram->registers, 0, sizeof memory->ram->registers); 308 + memset(&memory->ram->pcm, 0, sizeof memory->ram->pcm); 308 309 memset(memory->product.samples.buffer, 0, memory->product.samples.count * TIC80_SAMPLESIZE); 309 310 310 311 tic_api_music(memory, -1, 0, 0, false, false, -1, -1);
+7 -3
src/core/core.h
··· 116 116 117 117 struct 118 118 { 119 - tic_sound_register_data left[TIC_SOUND_CHANNELS]; 120 - tic_sound_register_data right[TIC_SOUND_CHANNELS]; 119 + struct sound_register_data 120 + { 121 + tic_sound_register_data data[TIC_SOUND_CHANNELS]; 122 + tic_sound_register_data pcm; 123 + } left, right; 121 124 } registers; 122 125 123 - struct 126 + struct sound_ring_buf 124 127 { 125 128 tic_sound_register registers[TIC_SOUND_CHANNELS]; 126 129 tic_stereo_volume stereo; 130 + tic_pcm pcm; 127 131 } sound_ringbuf[TIC_SOUND_RINGBUF_LEN]; 128 132 129 133 u32 sound_ringbuf_head;
+49 -31
src/core/sound.c
··· 25 25 #include "core.h" 26 26 27 27 #include <string.h> 28 + #include <limits.h> 28 29 #include "tic_assert.h" 29 30 30 31 #define ENVELOPE_FREQ_SCALE 2 31 32 #define SECONDS_PER_MINUTE 60 32 33 #define NOTES_PER_MINUTE (TIC80_FRAMERATE / NOTES_PER_BEAT * SECONDS_PER_MINUTE) 33 34 #define PIANO_START 8 35 + #define ENDTIME (CLOCKRATE / TIC80_FRAMERATE) 34 36 35 37 static const u16 NoteFreqs[] = { 0x10, 0x11, 0x12, 0x13, 0x15, 0x16, 0x17, 0x18, 0x1a, 0x1c, 0x1d, 0x1f, 0x21, 0x23, 0x25, 0x27, 0x29, 0x2c, 0x2e, 0x31, 0x34, 0x37, 0x3a, 0x3e, 0x41, 0x45, 0x49, 0x4e, 0x52, 0x57, 0x5c, 0x62, 0x68, 0x6e, 0x75, 0x7b, 0x83, 0x8b, 0x93, 0x9c, 0xa5, 0xaf, 0xb9, 0xc4, 0xd0, 0xdc, 0xe9, 0xf7, 0x106, 0x115, 0x126, 0x137, 0x14a, 0x15d, 0x172, 0x188, 0x19f, 0x1b8, 0x1d2, 0x1ee, 0x20b, 0x22a, 0x24b, 0x26e, 0x293, 0x2ba, 0x2e4, 0x310, 0x33f, 0x370, 0x3a4, 0x3dc, 0x417, 0x455, 0x497, 0x4dd, 0x527, 0x575, 0x5c8, 0x620, 0x67d, 0x6e0, 0x749, 0x7b8, 0x82d, 0x8a9, 0x92d, 0x9b9, 0xa4d, 0xaea, 0xb90, 0xc40, 0xcfa, 0xdc0, 0xe91, 0xf6f, 0x105a, 0x1153, 0x125b, 0x1372, 0x149a, 0x15d4, 0x1720, 0x1880 }; 36 38 static_assert(COUNT_OF(NoteFreqs) == NOTES * OCTAVES + PIANO_START, "count_of_freqs"); ··· 98 100 return CLAMP(Rate / freq - 1, MinPeriodValue, MaxPeriodValue); 99 101 } 100 102 101 - static inline s32 getAmp(const tic_sound_register* reg, s32 amp) 103 + static inline s32 getAmp(s32 volume, s32 amp) 102 104 { 103 - enum { AmpMax = (u16)-1 / 2 }; 104 - return (amp * AmpMax / MAX_VOLUME) * reg->volume / MAX_VOLUME / TIC_SOUND_CHANNELS; 105 + return amp * volume / MAX_VOLUME / (TIC_SOUND_CHANNELS + 1); 105 106 } 106 107 107 - static void runEnvelope(blip_buffer_t* blip, const tic_sound_register* reg, tic_sound_register_data* data, s32 end_time, u8 volume) 108 + static void runPcm(blip_buffer_t* blip, const tic_pcm* pcm, tic_sound_register_data* data) 108 109 { 109 - s32 period = freq2period(tic_sound_register_get_freq(reg) * ENVELOPE_FREQ_SCALE); 110 + enum{Period = ENDTIME / TIC_PCM_SIZE}; 110 111 111 - for (; data->time < end_time; data->time += period) 112 + for (data->time = 0; data->time < ENDTIME; data->time += Period, data->phase = (data->phase + 1) % TIC_PCM_SIZE) 112 113 { 113 - data->phase = (data->phase + 1) % WAVE_VALUES; 114 + update_amp(blip, data, getAmp(MAX_VOLUME, pcm->data[data->phase] * SHRT_MAX / UCHAR_MAX)); 115 + } 116 + } 114 117 115 - update_amp(blip, data, getAmp(reg, tic_tool_peek4(reg->waveform.data, data->phase) * volume / MAX_VOLUME)); 118 + static void runEnvelope(blip_buffer_t* blip, const tic_sound_register* reg, tic_sound_register_data* data, u8 stereo_volume) 119 + { 120 + s32 period = freq2period(tic_sound_register_get_freq(reg) * ENVELOPE_FREQ_SCALE); 121 + 122 + for (; data->time < ENDTIME; data->time += period, data->phase = (data->phase + 1) % WAVE_VALUES) 123 + { 124 + update_amp(blip, data, getAmp(reg->volume, tic_tool_peek4(reg->waveform.data, data->phase) * SHRT_MAX / MAX_VOLUME * stereo_volume / MAX_VOLUME)); 116 125 } 117 126 } 118 127 119 - static void runNoise(blip_buffer_t* blip, const tic_sound_register* reg, tic_sound_register_data* data, s32 end_time, u8 volume) 128 + static void runNoise(blip_buffer_t* blip, const tic_sound_register* reg, tic_sound_register_data* data, u8 stereo_volume) 120 129 { 121 130 // phase is noise LFSR, which must never be zero 122 131 if (data->phase == 0) ··· 125 134 s32 period = freq2period(tic_sound_register_get_freq(reg)); 126 135 s32 fb = *reg->waveform.data ? 0x14 : 0x12000; 127 136 128 - for (; data->time < end_time; data->time += period) 137 + for (; data->time < ENDTIME; data->time += period, data->phase = ((data->phase & 1) * fb) ^ (data->phase >> 1)) 129 138 { 130 - data->phase = ((data->phase & 1) * fb) ^ (data->phase >> 1); 131 - update_amp(blip, data, getAmp(reg, (data->phase & 1) ? volume : 0)); 139 + update_amp(blip, data, getAmp(reg->volume, (data->phase & 1) ? stereo_volume * SHRT_MAX / MAX_VOLUME : 0)); 132 140 } 133 141 } 134 142 ··· 502 510 setSfxChannelData(memory, index, note, octave, duration, channel, left, right, speed); 503 511 } 504 512 505 - static void stereo_synthesize(tic_core* core, tic_sound_register_data* registers, blip_buffer_t* blip, u8 stereoRight) 513 + static inline const struct sound_ring_buf *sound_ringbuf(tic_core* core) 506 514 { 507 - enum { EndTime = CLOCKRATE / TIC80_FRAMERATE }; 508 - s32 bufpos = (core->state.sound_ringbuf_tail + TIC_SOUND_RINGBUF_LEN - 1) % TIC_SOUND_RINGBUF_LEN; 515 + return &core->state.sound_ringbuf[(core->state.sound_ringbuf_tail + TIC_SOUND_RINGBUF_LEN - 1) % TIC_SOUND_RINGBUF_LEN]; 516 + } 517 + 518 + static void stereo_synthesize(tic_core* core, struct sound_register_data *regdata, blip_buffer_t* blip, u8 stereoRight) 519 + { 520 + const struct sound_ring_buf *ringbuf = sound_ringbuf(core); 521 + 509 522 for (s32 i = 0; i < TIC_SOUND_CHANNELS; ++i) 510 523 { 511 - u8 volume = tic_tool_peek4(&core->state.sound_ringbuf[bufpos].stereo, stereoRight + i * 2); 524 + u8 stereo_volume = tic_tool_peek4(&ringbuf->stereo, stereoRight + i * 2); 512 525 513 - const tic_sound_register* reg = &core->state.sound_ringbuf[bufpos].registers[i]; 514 - tic_sound_register_data* data = registers + i; 526 + const tic_sound_register* reg = &ringbuf->registers[i]; 527 + tic_sound_register_data* data = &regdata->data[i]; 515 528 516 529 tic_tool_noise(&reg->waveform) 517 - ? runNoise(blip, reg, data, EndTime, volume) 518 - : runEnvelope(blip, reg, data, EndTime, volume); 530 + ? runNoise(blip, reg, data, stereo_volume) 531 + : runEnvelope(blip, reg, data, stereo_volume); 519 532 520 - data->time -= EndTime; 533 + data->time -= ENDTIME; 521 534 } 522 535 523 - blip_end_frame(blip, EndTime); 536 + runPcm(blip, &ringbuf->pcm, &regdata->pcm); 537 + 538 + blip_end_frame(blip, ENDTIME); 524 539 } 525 540 526 541 void tic_core_synth_sound(tic_mem* memory) 527 542 { 528 - tic_core* core = (tic_core*)memory; 543 + tic_core *core = (tic_core*)memory; 544 + tic80 *product = &core->memory.product; 529 545 530 546 // synthesize sound using the register values found from the tail of the ring buffer 531 - stereo_synthesize(core, core->state.registers.left, core->blip.left, 0); 532 - stereo_synthesize(core, core->state.registers.right, core->blip.right, 1); 547 + stereo_synthesize(core, &core->state.registers.left, core->blip.left, 0); 548 + stereo_synthesize(core, &core->state.registers.right, core->blip.right, 1); 533 549 534 - blip_read_samples(core->blip.left, core->memory.product.samples.buffer, core->samplerate / TIC80_FRAMERATE, TIC80_SAMPLE_CHANNELS); 535 - blip_read_samples(core->blip.right, core->memory.product.samples.buffer + 1, core->samplerate / TIC80_FRAMERATE, TIC80_SAMPLE_CHANNELS); 550 + blip_read_samples(core->blip.left, product->samples.buffer, core->samplerate / TIC80_FRAMERATE, TIC80_SAMPLE_CHANNELS); 551 + blip_read_samples(core->blip.right, product->samples.buffer + 1, core->samplerate / TIC80_FRAMERATE, TIC80_SAMPLE_CHANNELS); 536 552 537 553 // if the head has advanced, we can advance the tail too. Otherwise, we just 538 554 // keep synthesizing audio using the last known register values, so at least we don't get crackles ··· 547 563 { 548 564 tic_core* core = (tic_core*)memory; 549 565 550 - for (s32 i = 0; i < TIC_SOUND_CHANNELS; ++i) 551 - memset(&memory->ram->registers[i], 0, sizeof(tic_sound_register)); 566 + ZEROMEM(memory->ram->registers); 567 + ZEROMEM(memory->ram->pcm); 552 568 553 569 memory->ram->stereo.data = -1; 554 570 ··· 568 584 tic_core* core = (tic_core*)memory; 569 585 570 586 // instead of synthesizing the sound right away, push the sound registers to the head of a ring buffer 571 - core->state.sound_ringbuf[core->state.sound_ringbuf_head].stereo = memory->ram->stereo; 572 - memcpy(&core->state.sound_ringbuf[core->state.sound_ringbuf_head], &memory->ram->registers, sizeof(tic_sound_register[4])); 587 + struct sound_ring_buf *ringbuf = &core->state.sound_ringbuf[core->state.sound_ringbuf_head]; 588 + memcpy(&ringbuf->registers, &memory->ram->registers, sizeof ringbuf->registers); 589 + ringbuf->stereo = memory->ram->stereo; 590 + ringbuf->pcm = memory->ram->pcm; 573 591 574 592 if (core->state.sound_ringbuf_head != (core->state.sound_ringbuf_tail + TIC_SOUND_RINGBUF_LEN - 2) % TIC_SOUND_RINGBUF_LEN) { 575 593 // note: we assume storing a 32 bit integer is atomic, that should hold on pretty much any modern processor
+1
src/studio/screens/console.c
··· 3075 3075 {offsetof(tic_ram, font.alt), "ALT FONT"}, 3076 3076 {offsetof(tic_ram, font.alt.params), "ALT FONT PARAMS"}, 3077 3077 {offsetof(tic_ram, mapping), "BUTTONS MAPPING"}, 3078 + {offsetof(tic_ram, pcm), "PCM SAMPLES"}, 3078 3079 {offsetof(tic_ram, free), "** RESERVED **"}, 3079 3080 {TIC_RAM_SIZE, ""}, 3080 3081 };
+7
src/tic.h
··· 91 91 #define WAVE_VALUE_BITS 4 92 92 #define WAVE_MAX_VALUE ((1 << WAVE_VALUE_BITS) - 1) 93 93 #define WAVE_SIZE (WAVE_VALUES * WAVE_VALUE_BITS / BITS_IN_BYTE) 94 + #define TIC_PCM_SIZE 128 94 95 95 96 #define TIC_BANKSIZE_BITS 16 96 97 #define TIC_BANK_SIZE (1 << TIC_BANKSIZE_BITS) // 64K ··· 620 621 u8 data[TIC_GAMEPADS * TIC_BUTTONS]; 621 622 } tic_mapping; 622 623 624 + typedef struct 625 + { 626 + u8 data[TIC_PCM_SIZE]; 627 + } tic_pcm; 628 + 623 629 typedef union 624 630 { 625 631 struct ··· 639 645 tic_flags flags; 640 646 tic_font font; 641 647 tic_mapping mapping; 648 + tic_pcm pcm; 642 649 643 650 u8 free; 644 651 };