diff options
Diffstat (limited to 'src/fruits/cmc/ui/util')
| -rw-r--r-- | src/fruits/cmc/ui/util/notcurses_ext.h | 20 | ||||
| -rw-r--r-- | src/fruits/cmc/ui/util/waveform.c | 202 | ||||
| -rw-r--r-- | src/fruits/cmc/ui/util/waveform.h | 111 |
3 files changed, 333 insertions, 0 deletions
diff --git a/src/fruits/cmc/ui/util/notcurses_ext.h b/src/fruits/cmc/ui/util/notcurses_ext.h new file mode 100644 index 0000000..b09754e --- /dev/null +++ b/src/fruits/cmc/ui/util/notcurses_ext.h @@ -0,0 +1,20 @@ +#pragma once + +#include <al/types.h> +#include <notcurses/notcurses.h> + +// Copy-paste from notcurses.h +static inline s32 ncplane_light_box(struct ncplane *n, u16 attr, u64 channels, s32 ystop, s32 xstop, u32 ctlword) +{ + s32 ret = 0; + nccell ul = NCCELL_TRIVIAL_INITIALIZER, ur = NCCELL_TRIVIAL_INITIALIZER; + nccell ll = NCCELL_TRIVIAL_INITIALIZER, lr = NCCELL_TRIVIAL_INITIALIZER; + nccell hl = NCCELL_TRIVIAL_INITIALIZER, vl = NCCELL_TRIVIAL_INITIALIZER; + if((ret = nccells_light_box(n, attr, channels, &ul, &ur, &ll, &lr, &hl, &vl)) == 0){ + ret = ncplane_box(n, &ul, &ur, &ll, &lr, &hl, &vl, ystop, xstop, ctlword); + } + nccell_release(n, &ul); nccell_release(n, &ur); + nccell_release(n, &ll); nccell_release(n, &lr); + nccell_release(n, &hl); nccell_release(n, &vl); + return ret; +} diff --git a/src/fruits/cmc/ui/util/waveform.c b/src/fruits/cmc/ui/util/waveform.c new file mode 100644 index 0000000..8d37543 --- /dev/null +++ b/src/fruits/cmc/ui/util/waveform.c @@ -0,0 +1,202 @@ +#include <al/log.h> +#include <math.h> +#include "waveform.h" + +#define WITHIN_RMS(low, high, rms) \ + ((low >= 0 && low <= rms) || (high < 0 && high >= -rms) || (low < 0 && high > 0 && rms > 0)) + +#define OUTPUT_WAVEFORM_PNG +//#define WAVEFORM_REFERENCE_MODE +#ifdef OUTPUT_WAVEFORM_PNG +#include <nnwt/file.h> +#include <nnwt/net.h> +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include <stb_image_write.h> + +// min/max: #BC615E, #F4EAE0 +// rms: #FF928F, #E4CAAF +// +// min/max: #D93A50, #b22f41 +// rms: #f44f7a, #c84064 +// extra: #f6ac7f, #F5F4FA, #5b524b +// left channel: n == 0, right channel: n == 1. +#define COLOR_FOR_PIXEL(n, rms) rms ? \ + n == 0 ? nn_htonl(0xE4CAAF99) : nn_htonl(0xFF928FFF) : \ + n == 0 ? nn_htonl(0xF4EAE099) : nn_htonl(0xBC615EFF) + +// ss: current sample, ns: next sample. +#define HIT_WAVE(low, high, ss, ns) \ + ((ss <= low && ns > low) || (ss > high && ns <= high) || (ss > low && ns <= high)) + +static void test_write_bitmap(struct cmc_list_entry *entry, u32 width, u32 height, u32 **rgba) +{ + f64 start = nn_get_tick(); + + *rgba = al_calloc(width * height, 4); + + u32 channels = entry->raw.fmt.channel_count; + u32 samples_per_column = entry->raw.sample_count / width; + + s32 wave_min = INT16_MIN; + s32 wave_max = INT16_MAX; + s32 step = (wave_max * 2 + (height - 1)) / height; + //s32 step = (wave_max * 2 + (height / 2)) / height; + + s16 *steps = al_malloc(sizeof(s16) * (height + 1)); + for (s32 i = 0; i <= (s32)height; i++) { + steps[i] = (s16)MAX(wave_max - step * i, wave_min); + } + //steps[height] = wave_min; + al_assert(steps[height] == wave_min); + + s64 rms = 0; + s16 min, max; + s16 low, high; + s16 *data = (s16 *)entry->raw.data; + const u32 samples_stride = samples_per_column * channels; + for (u32 i = 0; i < width; i++) { + u32 f = i * samples_stride; + for (u32 n = 0; n < channels; n++) { + rms = 0; + min = wave_max, max = wave_min; + for (u32 m = 0; m <= samples_stride; m += channels) { + s16 ss = data[f + m + n]; + rms += ss * ss; + min = MIN(min, ss); + max = MAX(max, ss); + } + rms /= samples_per_column; + rms = sqrt(rms); +#ifndef WAVEFORM_REFERENCE_MODE + for (u32 j = 0; j < height; j++) { + low = steps[j + 1], high = steps[j]; + if (low < max && high >= min) { + (*rgba)[j * width + i] = COLOR_FOR_PIXEL(n, WITHIN_RMS(low, high, rms)); + } + } +#else + for (u32 m = 0; m < samples_stride; m += channels) { + s16 ss = data[f + m + n]; + s16 ns = data[f + m + n + channels]; + for (u32 j = 0; j < height; j++) { + low = steps[j + 1], high = steps[j]; + if (HIT_WAVE(low, high, ss, ns)) { + (*rgba)[j * width + i] = COLOR_FOR_PIXEL(n, WITHIN_RMS(low, high, rms)); + } + } + } +#endif + } + } + + log_info("generating waveform took: %.2fs.", nn_get_tick() - start); + + //stbi_write_png("./waveform.png", width, height, 4, *rgba, width * 4); + + /* + struct nn_file file; + nn_file_open(&file, &al_str_c("./raw_samples.raw"), NNWT_FILE_CREATE); + size_t bytes = entry->raw.sample_count * entry->raw.fmt.channel_count * camu_audio_format_bytes_per_sample(&entry->raw.fmt); + nn_file_write(&file, entry->raw.data, bytes); + nn_file_close(&file); + */ +} +#endif + +static const char *octant_lut[] = { + " ", "๐บจ", "๐บซ", "๐ฎ", "๐ด", "โ", "๐ด", "๐ด", "๐ด", "๐ด", "โ", "๐ด
", "๐ด", "๐ด", "๐ด", "โ", + "๐ด", "๐ด", "๐ด", "๐ด", "๐ฏฆ", "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", + "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", "๐ด", "๐ฏง", "๐ด ", "๐ดก", "๐ดข", "๐ดฃ", "๐ดค", "๐ดฅ", "๐ดฆ", + "๐ดง", "๐ดจ", "๐ดฉ", "๐ดช", "๐ดซ", "๐ดฌ", "๐ดญ", "๐ดฎ", "๐ดฏ", "๐ดฐ", "๐ดฑ", "๐ดฒ", "๐ดณ", "๐ดด", "๐ดต", "๐ฎ
", + "๐บฃ", "๐ดถ", "๐ดท", "๐ดธ", "๐ดน", "๐ดบ", "๐ดป", "๐ดผ", "๐ดฝ", "๐ดพ", "๐ดฟ", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", + "โ", "๐ต
", "๐ต", "๐ต", "๐ต", "โ", "๐ต", "๐ต", "๐ต", "๐ต", "โ", "๐ต", "๐ต", "๐ต", "๐ต", "โ", + "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต", "๐ต ", + "๐ตก", "๐ตข", "๐ตฃ", "๐ตค", "๐ตฅ", "๐ตฆ", "๐ตง", "๐ตจ", "๐ตฉ", "๐ตช", "๐ตซ", "๐ตฌ", "๐ตญ", "๐ตฎ", "๐ตฏ", "๐ตฐ", + "๐บ ", "๐ตฑ", "๐ตฒ", "๐ตณ", "๐ตด", "๐ตต", "๐ตถ", "๐ตท", "๐ตธ", "๐ตน", "๐ตบ", "๐ตป", "๐ตผ", "๐ตฝ", "๐ตพ", "๐ตฟ", + "๐ถ", "๐ถ", "๐ถ", "๐ถ", "๐ถ", "๐ถ
", "๐ถ", "๐ถ", "๐ถ", "๐ถ", "๐ถ", "๐ถ", "๐ถ", "๐ถ", "๐ถ", "๐ถ", + "โ", "๐ถ", "๐ถ", "๐ถ", "๐ถ", "โ", "๐ถ", "๐ถ", "๐ถ", "๐ถ", "โ", "๐ถ", "๐ถ", "๐ถ", "๐ถ", "โ", + "๐ถ", "๐ถ", "๐ถ", "๐ถ", "๐ถ ", "๐ถก", "๐ถข", "๐ถฃ", "๐ถค", "๐ถฅ", "๐ถฆ", "๐ถง", "๐ถจ", "๐ถฉ", "๐ถช", "๐ถซ", + "โ", "๐ถฌ", "๐ถญ", "๐ถฎ", "๐ถฏ", "๐ถฐ", "๐ถฑ", "๐ถฒ", "๐ถณ", "๐ถด", "๐ถต", "๐ถถ", "๐ถท", "๐ถธ", "๐ถน", "๐ถบ", + "๐ถป", "๐ถผ", "๐ถฝ", "๐ถพ", "๐ถฟ", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท
", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", + "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", "๐ท", + "โ", "๐ท", "๐ท", "๐ท", "๐ท", "โ", "๐ท", "๐ท ", "๐ทก", "๐ทข", "โ", "๐ทฃ", "โ", "๐ทค", "๐ทฅ", "โ" +}; + +#define RMS_BIT (1 << 8) + +void cmc_draw_waveform(struct cmc_list_entry *entry, u32 width, u32 height, bool include_rms, char ***buf, u32 **rgba) +{ +#ifdef OUTPUT_WAVEFORM_PNG + test_write_bitmap(entry, width, height, rgba); + return; +#endif + +// u32 channels = entry->raw.fmt.channel_count; +// u32 samples_per_column = entry->raw.sample_count / (width * 2); +// +// s32 pixel_height = height * 4; +// s32 wave_min = INT16_MIN; +// s32 wave_max = INT16_MAX; +// s32 step = (wave_max * 2 + (pixel_height - 1)) / pixel_height; +// +// s16 *steps = al_malloc(sizeof(s16) * (pixel_height + 1)); +// for (s32 i = 0; i <= (s32)pixel_height; i++) { +// steps[i] = (s16)MAX(wave_max - step * i, wave_min); +// } +// al_assert(steps[pixel_height] == wave_min); +// +// s64 rms = 0; +// s16 min, max; +// s16 low, high; +// s16 *data = (s16 *)entry->raw.data; +// const u32 samples_stride = samples_per_column * channels; +// u16 masks_for_chars[height]; +// //u32 slen[height]; +// //al_memset(slen, 0, sizeof(u32) * height); +// for (u32 i = 0; i < width; i++) { +// al_memset(masks_for_chars, 0, sizeof(u16) * height); +// for (u32 k = 0; k < 2; k++) { +// u32 f = (i * 2 + k) * samples_stride; +// for (u32 n = 0; n < channels; n++) { +// rms = 0; +// min = wave_max, max = wave_min; +// for (u32 m = 0; m <= samples_stride; m += channels) { +// s16 ss = data[f + m + n]; +// rms += ss * ss; +// min = MIN(min, ss); +// max = MAX(max, ss); +// } +// rms /= samples_per_column; +// rms = sqrt(rms); +// for (u32 j = 0; j < height; j++) { +// for (u32 l = 0; l < 4; l++) { +// u32 step = j * 4 + l; +// low = steps[step + 1], high = steps[step]; +// if (low < max && high >= min) { +// if (include_rms && WITHIN_RMS(low, high, rms)) { +// masks_for_chars[j] |= RMS_BIT; +// } else { +// masks_for_chars[j] |= 1 << (l * 2 + k); +// } +// } +// } +// } +// } +// } +// for (u32 j = 0; j < height; j++) { +// if (masks_for_chars[j] & RMS_BIT) { +// buf[j][i][0] = 'R'; +// masks_for_chars[j] &= ~RMS_BIT; +// } +// u32 len = masks_for_chars[j] == 0 ? 2 : 5; +// al_memcpy(buf[j][i] + 1, octant_lut[masks_for_chars[j]], len); +// //slen[j] += len; +// } +// } +// +// /* +// for (u32 j = 0; j < height; j++) { +// buf[j][slen[j]] = '\0'; +// } +// */ +} diff --git a/src/fruits/cmc/ui/util/waveform.h b/src/fruits/cmc/ui/util/waveform.h new file mode 100644 index 0000000..763f54a --- /dev/null +++ b/src/fruits/cmc/ui/util/waveform.h @@ -0,0 +1,111 @@ +/* +notcurses.h: +Halves + +โ โ + +Quadrants + +โ โ โ โ โ โ โ + +Sextants + +๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ
๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ ๐ฌ + +https://wiki.ourworldoftext.com/wiki/Octant: +Octants + + ๐บจ ๐บซ ๐ฎ ๐ด โ ๐ด ๐ด ๐ด ๐ด โ ๐ด
๐ด ๐ด ๐ด โ + +๐ด ๐ด ๐ด ๐ด ๐ฏฆ ๐ด ๐ด ๐ด ๐ด ๐ด ๐ด ๐ด ๐ด ๐ด ๐ด ๐ด + +๐ด ๐ด ๐ด ๐ด ๐ด ๐ด ๐ด ๐ด ๐ฏง ๐ด ๐ดก ๐ดข ๐ดฃ ๐ดค ๐ดฅ ๐ดฆ + +๐ดง ๐ดจ ๐ดฉ ๐ดช ๐ดซ ๐ดฌ ๐ดญ ๐ดฎ ๐ดฏ ๐ดฐ ๐ดฑ ๐ดฒ ๐ดณ ๐ดด ๐ดต ๐ฎ
+ +๐บฃ ๐ดถ ๐ดท ๐ดธ ๐ดน ๐ดบ ๐ดป ๐ดผ ๐ดฝ ๐ดพ ๐ดฟ ๐ต ๐ต ๐ต ๐ต ๐ต + +โ ๐ต
๐ต ๐ต ๐ต โ ๐ต ๐ต ๐ต ๐ต โ ๐ต ๐ต ๐ต ๐ต โ + +๐ต ๐ต ๐ต ๐ต ๐ต ๐ต ๐ต ๐ต ๐ต ๐ต ๐ต ๐ต ๐ต ๐ต ๐ต ๐ต + +๐ตก ๐ตข ๐ตฃ ๐ตค ๐ตฅ ๐ตฆ ๐ตง ๐ตจ ๐ตฉ ๐ตช ๐ตซ ๐ตฌ ๐ตญ ๐ตฎ ๐ตฏ ๐ตฐ + +๐บ ๐ตฑ ๐ตฒ ๐ตณ ๐ตด ๐ตต ๐ตถ ๐ตท ๐ตธ ๐ตน ๐ตบ ๐ตป ๐ตผ ๐ตฝ ๐ตพ ๐ตฟ + +๐ถ ๐ถ ๐ถ ๐ถ ๐ถ ๐ถ
๐ถ ๐ถ ๐ถ ๐ถ ๐ถ ๐ถ ๐ถ ๐ถ ๐ถ ๐ถ + +โ ๐ถ ๐ถ ๐ถ ๐ถ โ ๐ถ ๐ถ ๐ถ ๐ถ โ ๐ถ ๐ถ ๐ถ ๐ถ โ + +๐ถ ๐ถ ๐ถ ๐ถ ๐ถ ๐ถก ๐ถข ๐ถฃ ๐ถค ๐ถฅ ๐ถฆ ๐ถง ๐ถจ ๐ถฉ ๐ถช ๐ถซ + +โ ๐ถฌ ๐ถญ ๐ถฎ ๐ถฏ ๐ถฐ ๐ถฑ ๐ถฒ ๐ถณ ๐ถด ๐ถต ๐ถถ ๐ถท ๐ถธ ๐ถน ๐ถบ + +๐ถป ๐ถผ ๐ถฝ ๐ถพ ๐ถฟ ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท
๐ท ๐ท ๐ท ๐ท ๐ท + +๐ท ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท ๐ท + +โ ๐ท ๐ท ๐ท ๐ท โ ๐ท ๐ท ๐ทก ๐ทข โ ๐ทฃ โ ๐ทค ๐ทฅ โ + +AAAAAAAAAAAAAAAA + +โ โ ๐ถป ๐ท โ โ ๐ท ๐ทก โ
โ ๐ทค ๐ทฅ โ โ + + โโ + ๐ทโ + + โ + โ + โ + ๐ท + +โ๐ดง๐ด + + + โโ๐ทโโ๐ทกโ
โ๐ทฅโโโโโโ๐ทฅโโ
๐ทกโโ๐ทโโ +โโ๐ทโโ๐ทกโ
โ๐ทฅโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ๐ทฅโโ
๐ทกโโ๐ทโโ + + +โโ๐ทคโโ
๐ทโโ๐ถปโโ + +โ๐ตโ๐ท +โโโโโ + +0 +1 ๐บจ +1 << 1 ๐บซ +1 << 2 ๐ด +1 << 3 ๐ด +1 << 4 ๐ด +1 << 5 ๐ด +1 << 6 ๐บฃ +1 << 7 ๐บ + +๐ดข 0b00101011 + +๐บจ๐บซ๐ฎ๐ดโ๐ด๐ด๐ด๐ดโ๐ด
๐ด๐ด๐ดโ๐ด๐ด๐ด๐ด๐ฏฆ๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ด๐ฏง๐ด ๐ดก๐ดข๐ดฃ๐ดค๐ดฅ๐ดฆ๐ดง๐ดจ๐ดฉ๐ดช๐ดซ๐ดฌ๐ดญ๐ดฎ๐ดฏ๐ดฐ๐ดฑ๐ดฒ๐ดณ๐ดด๐ดต๐ฎ
๐บฃ๐ดถ๐ดท๐ดธ๐ดน๐ดบ๐ดป๐ดผ๐ดฝ๐ดพ๐ดฟ๐ต๐ต๐ต๐ต๐ตโ๐ต
๐ต๐ต๐ตโ๐ต๐ต๐ต๐ตโ๐ต๐ต๐ต๐ตโ๐ต๐ต๐ต๐ต๐ต๐ต๐ต๐ต๐ต๐ต๐ต๐ต๐ต๐ต๐ต๐ต ๐ตก๐ตข๐ตฃ๐ตค๐ตฅ๐ตฆ๐ตง๐ตจ๐ตฉ๐ตช๐ตซ๐ตฌ๐ตญ๐ตฎ๐ตฏ๐ตฐ๐บ ๐ตฑ๐ตฒ๐ตณ๐ตด๐ตต๐ตถ๐ตท๐ตธ๐ตน๐ตบ๐ตป๐ตผ๐ตฝ๐ตพ๐ตฟ๐ถ๐ถ๐ถ๐ถ๐ถ๐ถ
๐ถ๐ถ๐ถ๐ถ๐ถ๐ถ๐ถ๐ถ๐ถ๐ถโ๐ถ๐ถ๐ถ๐ถโ๐ถ๐ถ๐ถ๐ถโ๐ถ๐ถ๐ถ๐ถโ๐ถ๐ถ๐ถ๐ถ๐ถ ๐ถก๐ถข๐ถฃ๐ถค๐ถฅ๐ถฆ๐ถง๐ถจ๐ถฉ๐ถช๐ถซโ๐ถฌ๐ถญ๐ถฎ๐ถฏ๐ถฐ๐ถฑ๐ถฒ๐ถณ๐ถด๐ถต๐ถถ๐ถท๐ถธ๐ถน๐ถบ๐ถป๐ถผ๐ถฝ๐ถพ๐ถฟ๐ท๐ท๐ท๐ท๐ท๐ท
๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ท๐ทโ๐ท๐ท๐ท๐ทโ๐ท๐ท ๐ทก๐ทขโ๐ทฃโ๐ทค๐ทฅโ +*/ + +#include <al/types.h> + +#include "../../cmc.h" + +/* +static const char *bar_lut[] = { + [0] = " ๐บ โ๐ถโ" , + [1] = "๐บฃโ๐ท๐ท๐ท", + [2] = "โ๐ถปโ๐ทก๐ทฅ", + [3] = "๐ต๐ถฟ๐ทโ๐ทฅ", + [4] = "โ๐ทโ๐ทคโ" +}; + +static const char *bar_bottom_lut[] = { + [0] = " ๐บซโ๐ดกโ" , + [1] = "๐บจ๐ฎ๐ด
๐ดข๐ถ", + [2] = "โ๐ดโ๐ดฆโ", + [3] = "๐ด๐ด๐ด๐ฎ
๐ถซ", + [4] = "โ๐ตโ๐ตฐโ" +}; +*/ + +void cmc_draw_waveform(struct cmc_list_entry *entry, u32 width, u32 height, bool include_rms, char ***buf, u32 **rgba); |