diff options
| author | Takamichi Horikawa <takamichiho@gmail.com> | 2017-09-12 21:24:16 +0900 | 
|---|---|---|
| committer | Takamichi Horikawa <takamichiho@gmail.com> | 2017-09-12 21:24:16 +0900 | 
| commit | 8435fa6d33704c5170635f9a53c17142f69117e4 (patch) | |
| tree | 509815a4150bac919b6411bbba90f7bddf2b7d18 | |
| parent | 676390c58c6367bcfeda901456d637939645b78e (diff) | |
fmdsp: pacc: add level, fft
| -rw-r--r-- | fmdsp/fmdsp-pacc.c | 358 | ||||
| -rw-r--r-- | fmdsp/fmdsp-pacc.h | 4 | ||||
| -rw-r--r-- | sdl/main.c | 22 | ||||
| -rw-r--r-- | sdl/osx/Makefile | 2 | ||||
| -rw-r--r-- | sdl/unix/Makefile | 4 | ||||
| -rw-r--r-- | sdl/win/Makefile | 2 | 
6 files changed, 385 insertions, 7 deletions
| diff --git a/fmdsp/fmdsp-pacc.c b/fmdsp/fmdsp-pacc.c index 815e323..bf76693 100644 --- a/fmdsp/fmdsp-pacc.c +++ b/fmdsp/fmdsp-pacc.c @@ -4,12 +4,15 @@  #include "fmdriver/fmdriver.h"  #include "libopna/opna.h"  #include "version.h" +#include "fft/fft.h"  #include "fmdsp_sprites.h"  #include <stdlib.h>  #include <string.h>  #include "fmdsp_platform_info.h" +#include <math.h> +  enum {    FADEDELTA = 16,  }; @@ -105,10 +108,11 @@ static const uint8_t track_disp_table_13[] = {  struct fmdsp_pacc {    struct pacc_ctx *pc;    struct pacc_vtable pacc; -  struct pacc_tex *tex_font, *tex_checker, *tex_key_left, *tex_key_right, *tex_key_mask, *tex_key_bg, *tex_num, *tex_dt_sign, *tex_solid, *tex_vertical, *tex_horizontal, *tex_logo, *tex_ver, *tex_text, *tex_tri, *tex_curl_left, *tex_curl_right, *tex_play, *tex_stop, *tex_pause, *tex_fade, *tex_ff, *tex_rew, *tex_floppy, *tex_circle; -  struct pacc_buf *buf_font_7, *buf_font_2, *buf_font_2_d, *buf_font_1, *buf_font_1_d, *buf_checker, *buf_key_left, *buf_key_right, *buf_key_mask, *buf_key_mask_sub, *buf_key_bg, *buf_num, *buf_dt_sign, *buf_solid_2, *buf_solid_2_d, *buf_solid_3, *buf_solid_3_d, *buf_solid_7, *buf_solid_7_d, *buf_vertical_2, *buf_vertical_3, *buf_vertical_7, *buf_logo, *buf_ver, *buf_text, *buf_tri, *buf_tri_7, *buf_curl_left, *buf_curl_right, *buf_play, *buf_stop, *buf_pause, *buf_fade, *buf_ff, *buf_rew, *buf_floppy, *buf_circle; +  struct pacc_tex *tex_font, *tex_checker, *tex_key_left, *tex_key_right, *tex_key_mask, *tex_key_bg, *tex_num, *tex_dt_sign, *tex_solid, *tex_vertical, *tex_horizontal, *tex_logo, *tex_ver, *tex_text, *tex_tri, *tex_curl_left, *tex_curl_right, *tex_play, *tex_stop, *tex_pause, *tex_fade, *tex_ff, *tex_rew, *tex_floppy, *tex_circle, *tex_panpot; +  struct pacc_buf *buf_font_7, *buf_font_2, *buf_font_2_d, *buf_font_1, *buf_font_1_d, *buf_checker, *buf_checker_1, *buf_key_left, *buf_key_right, *buf_key_mask, *buf_key_mask_sub, *buf_key_bg, *buf_num, *buf_dt_sign, *buf_solid_2, *buf_solid_2_d, *buf_solid_3, *buf_solid_3_d, *buf_solid_7, *buf_solid_7_d, *buf_vertical_2, *buf_vertical_3, *buf_vertical_7, *buf_horizontal_2_d, *buf_horizontal_3, *buf_horizontal_7_d, *buf_logo, *buf_ver, *buf_text, *buf_tri, *buf_tri_7, *buf_curl_left, *buf_curl_right, *buf_play, *buf_stop, *buf_pause, *buf_fade, *buf_ff, *buf_rew, *buf_floppy, *buf_circle, *buf_panpot_1_d, *buf_panpot_5_d;    struct opna *opna;    struct fmdriver_work *work; +  struct fmplayer_fft_input_data *fftin;    uint8_t curr_palette[FMDSP_PALETTE_COLORS*3];    uint8_t target_palette[FMDSP_PALETTE_COLORS*3];    enum fmdsp_left_mode lmode; @@ -119,6 +123,12 @@ struct fmdsp_pacc {    int cpuusage;    int fps;    uint64_t framecnt; +  uint8_t fftdata[FFTDISPLEN]; +  uint8_t fftcnt[FFTDISPLEN]; +  uint8_t fftdropdiv[FFTDISPLEN]; +  uint8_t leveldata[FMDSP_LEVEL_COUNT]; +  uint8_t levelcnt[FMDSP_LEVEL_COUNT]; +  uint8_t leveldropdiv[FMDSP_LEVEL_COUNT];  };  static struct pacc_tex *tex_from_font( @@ -148,6 +158,7 @@ void fmdsp_pacc_release(struct fmdsp_pacc *fp) {        fp->pacc.buf_delete(fp->buf_font_2_d);        fp->pacc.buf_delete(fp->buf_font_7);        fp->pacc.buf_delete(fp->buf_checker); +      fp->pacc.buf_delete(fp->buf_checker_1);        fp->pacc.buf_delete(fp->buf_key_left);        fp->pacc.buf_delete(fp->buf_key_right);        fp->pacc.buf_delete(fp->buf_key_mask); @@ -164,6 +175,9 @@ void fmdsp_pacc_release(struct fmdsp_pacc *fp) {        fp->pacc.buf_delete(fp->buf_vertical_2);        fp->pacc.buf_delete(fp->buf_vertical_3);        fp->pacc.buf_delete(fp->buf_vertical_7); +      fp->pacc.buf_delete(fp->buf_horizontal_2_d); +      fp->pacc.buf_delete(fp->buf_horizontal_3); +      fp->pacc.buf_delete(fp->buf_horizontal_7_d);        fp->pacc.buf_delete(fp->buf_logo);        fp->pacc.buf_delete(fp->buf_ver);        fp->pacc.buf_delete(fp->buf_text); @@ -179,6 +193,8 @@ void fmdsp_pacc_release(struct fmdsp_pacc *fp) {        fp->pacc.buf_delete(fp->buf_rew);        fp->pacc.buf_delete(fp->buf_floppy);        fp->pacc.buf_delete(fp->buf_circle); +      fp->pacc.buf_delete(fp->buf_panpot_1_d); +      fp->pacc.buf_delete(fp->buf_panpot_5_d);        fp->pacc.tex_delete(fp->tex_font);        fp->pacc.tex_delete(fp->tex_checker);        fp->pacc.tex_delete(fp->tex_key_left); @@ -204,6 +220,7 @@ void fmdsp_pacc_release(struct fmdsp_pacc *fp) {        fp->pacc.tex_delete(fp->tex_rew);        fp->pacc.tex_delete(fp->tex_floppy);        fp->pacc.tex_delete(fp->tex_circle); +      fp->pacc.tex_delete(fp->tex_panpot);      }      free(fp);    } @@ -510,6 +527,8 @@ struct fmdsp_pacc *fmdsp_pacc_init(    if (!fp->tex_floppy) goto err;    fp->tex_circle = fp->pacc.gen_tex(fp->pc, CIRCLE_W, CIRCLE_H*9);    if (!fp->tex_circle) goto err; +  fp->tex_panpot = fp->pacc.gen_tex(fp->pc, PANPOT_W, PANPOT_H*6); +  if (!fp->tex_panpot) goto err;    uint8_t *buf;    buf = fp->pacc.tex_lock(fp->tex_checker); @@ -571,6 +590,9 @@ struct fmdsp_pacc *fmdsp_pacc_init(    buf = fp->pacc.tex_lock(fp->tex_floppy);    memcpy(buf, s_floppy, FLOPPY_W*FLOPPY_H);    fp->pacc.tex_unlock(fp->tex_floppy); +  buf = fp->pacc.tex_lock(fp->tex_panpot); +  memcpy(buf, s_panpot, PANPOT_W*PANPOT_H*6); +  fp->pacc.tex_unlock(fp->tex_panpot);    buf = fp->pacc.tex_lock(fp->tex_solid);    buf[0] = 1;    fp->pacc.tex_unlock(fp->tex_solid); @@ -633,6 +655,8 @@ struct fmdsp_pacc *fmdsp_pacc_init(    if (!fp->buf_font_7) goto err;    fp->buf_checker = fp->pacc.gen_buf(fp->pc, fp->tex_checker, pacc_buf_mode_static);    if (!fp->buf_checker) goto err; +  fp->buf_checker_1 = fp->pacc.gen_buf(fp->pc, fp->tex_checker, pacc_buf_mode_static); +  if (!fp->buf_checker_1) goto err;    fp->buf_key_left = fp->pacc.gen_buf(fp->pc, fp->tex_key_left, pacc_buf_mode_static);    if (!fp->buf_key_left) goto err;    fp->buf_key_right = fp->pacc.gen_buf(fp->pc, fp->tex_key_right, pacc_buf_mode_static); @@ -665,6 +689,12 @@ struct fmdsp_pacc *fmdsp_pacc_init(    if (!fp->buf_vertical_3) goto err;    fp->buf_vertical_7 = fp->pacc.gen_buf(fp->pc, fp->tex_vertical, pacc_buf_mode_stream);    if (!fp->buf_vertical_7) goto err; +  fp->buf_horizontal_2_d = fp->pacc.gen_buf(fp->pc, fp->tex_horizontal, pacc_buf_mode_stream); +  if (!fp->buf_horizontal_2_d) goto err; +  fp->buf_horizontal_3 = fp->pacc.gen_buf(fp->pc, fp->tex_horizontal, pacc_buf_mode_static); +  if (!fp->buf_horizontal_3) goto err; +  fp->buf_horizontal_7_d = fp->pacc.gen_buf(fp->pc, fp->tex_horizontal, pacc_buf_mode_stream); +  if (!fp->buf_horizontal_7_d) goto err;    fp->buf_logo = fp->pacc.gen_buf(fp->pc, fp->tex_logo, pacc_buf_mode_static);    if (!fp->buf_logo) goto err;    fp->buf_ver = fp->pacc.gen_buf(fp->pc, fp->tex_ver, pacc_buf_mode_static); @@ -695,6 +725,10 @@ struct fmdsp_pacc *fmdsp_pacc_init(    if (!fp->buf_floppy) goto err;    fp->buf_circle = fp->pacc.gen_buf(fp->pc, fp->tex_circle, pacc_buf_mode_stream);    if (!fp->buf_circle) goto err; +  fp->buf_panpot_1_d = fp->pacc.gen_buf(fp->pc, fp->tex_panpot, pacc_buf_mode_stream); +  if (!fp->buf_panpot_1_d) goto err; +  fp->buf_panpot_5_d = fp->pacc.gen_buf(fp->pc, fp->tex_panpot, pacc_buf_mode_stream); +  if (!fp->buf_panpot_5_d) goto err;    fp->pacc.buf_rect_off(fp->pc, fp->buf_checker, 1, CHECKER_Y, PC98_W-1, CHECKER_H, 1, 0);    fp->pacc.buf_rect(fp->pc, fp->buf_checker, 0, CHECKER_Y+2, 1, CHECKER_H-4); @@ -946,6 +980,144 @@ static void init_default(struct fmdsp_pacc *fp) {        fp->pc, fp->buf_solid_7,        352+142, 70-2, 1, 1); +  // fft +  for (int i = 0; i < FFTDISPLEN; i++) { +    fp->pacc.buf_rect( +        fp->pc, fp->buf_horizontal_3, +        SPECTRUM_X+i*4, SPECTRUM_Y-62, +        3, 64); +  } +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      SPECTRUM_X+197, SPECTRUM_Y-71, +      "SPECTRUM"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      SPECTRUM_X+241, SPECTRUM_Y-71, +      "ANAL"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      SPECTRUM_X+260, SPECTRUM_Y-71, +      "YzER"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      SPECTRUM_X-24, SPECTRUM_Y+1, +      "FREQ"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      SPECTRUM_X+36, SPECTRUM_Y+1, +      "250"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      SPECTRUM_X+83, SPECTRUM_Y+1, +      "500"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      SPECTRUM_X+133, SPECTRUM_Y+1, +      "1"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      SPECTRUM_X+133+6, SPECTRUM_Y+1, +      "k"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      SPECTRUM_X+183, SPECTRUM_Y+1, +      "2k"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      SPECTRUM_X+230, SPECTRUM_Y+1, +      "4k"); +  fp->pacc.buf_rect( +      fp->pc, fp->buf_solid_2, +      SPECTRUM_X-2, SPECTRUM_Y-62, 1, 63); +  for (int i = 0; i < 32; i++) { +    fp->pacc.buf_rect( +        fp->pc, fp->buf_solid_2, +        SPECTRUM_X-3 - (((i % 4) == 3) ? 1 : 0), SPECTRUM_Y-62+2*i, +        ((i % 4) == 3) ? 2 : 1, 1); +  } +  fp->pacc.buf_rect( +      fp->pc, fp->buf_checker_1, +      SPECTRUM_X+1, SPECTRUM_Y+4, 34, 1); +  fp->pacc.buf_rect( +      fp->pc, fp->buf_checker_1, +      SPECTRUM_X+52, SPECTRUM_Y+4, 30, 1); +  fp->pacc.buf_rect( +      fp->pc, fp->buf_checker_1, +      SPECTRUM_X+99, SPECTRUM_Y+4, 34, 1); +  fp->pacc.buf_rect( +      fp->pc, fp->buf_checker_1, +      SPECTRUM_X+144, SPECTRUM_Y+4, 38, 1); +  fp->pacc.buf_rect( +      fp->pc, fp->buf_checker_1, +      SPECTRUM_X+193, SPECTRUM_Y+4, 36, 1); +  fp->pacc.buf_rect( +      fp->pc, fp->buf_checker_1, +      SPECTRUM_X+240, SPECTRUM_Y+4, 40, 1); +  // level +  for (int c = 0; c < FMDSP_LEVEL_COUNT; c++) { +    fp->pacc.buf_rect( +        fp->pc, fp->buf_horizontal_3, +        LEVEL_X + LEVEL_W*c, LEVEL_Y, +        LEVEL_DISP_W, 64); +  } +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      LEVEL_TEXT_X+5, LEVEL_TEXT_Y, +      "ON"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      LEVEL_TEXT_X, LEVEL_TEXT_Y+8, +      "PAN"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      LEVEL_TEXT_X-5, LEVEL_TEXT_Y+16, +      "PROG"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_1, +      LEVEL_TEXT_X, LEVEL_TEXT_Y+23, +      "KEY"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      LEVEL_X+LEVEL_W*0, LEVEL_TRACK_Y, +      "FM1"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      LEVEL_X+LEVEL_W*3, LEVEL_TRACK_Y, +      "FM4"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      LEVEL_X+LEVEL_W*6, LEVEL_TRACK_Y, +      "SSG"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      LEVEL_X+LEVEL_W*9, LEVEL_TRACK_Y, +      "RHY"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      LEVEL_X+LEVEL_W*10, LEVEL_TRACK_Y, +      "ADP"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      LEVEL_X+LEVEL_W*11, LEVEL_TRACK_Y, +      "PPZ"); +  fp->pacc.buf_rect( +      fp->pc, fp->buf_solid_2, +      LEVEL_X-2, LEVEL_Y, 1, 63); +  for (int i = 0; i < 32; i++) { +    fp->pacc.buf_rect( +        fp->pc, fp->buf_solid_2, +        LEVEL_X-3-((i % 4) == 3), LEVEL_Y+i*2, +        ((i % 4) == 3) + 1, 1); +  } +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      LEVEL_X-9, LEVEL_Y-1, +      "0"); +  fp->pacc.buf_printf( +      fp->pc, fp->buf_font_7, +      LEVEL_X-19, LEVEL_Y+56, +      "-48");  }  static void update_default(struct fmdsp_pacc *fp) { @@ -1069,9 +1241,176 @@ static void update_default(struct fmdsp_pacc *fp) {        fp->pc, fp->buf_circle,        CIRCLE_X, CIRCLE_Y, CIRCLE_W, CIRCLE_H,        0, CIRCLE_H*clock); + +  // fft +  struct fmplayer_fft_disp_data ddata = {0}; +  fft_calc(&ddata, fp->fftin); +  for (int x = 0; x < FFTDISPLEN; x++) { +    fp->pacc.buf_rect( +        fp->pc, fp->buf_horizontal_2_d, +        SPECTRUM_X+x*4, SPECTRUM_Y-62+(32-ddata.buf[x])*2, 3, ddata.buf[x]*2); +  } +  for (int i = 0; i < FFTDISPLEN; i++) { +    if (fp->fftdata[i] <= ddata.buf[i]) { +      fp->fftdata[i] = ddata.buf[i]; +      fp->fftcnt[i] = 30; +    } else { +      if (fp->fftcnt[i]) { +	fp->fftcnt[i]--; +      } else { +	if (fp->fftdata[i]) { +	  if (fp->fftdropdiv[i]) { +	    fp->fftdropdiv[i]--; +	  } else { +	    static const uint8_t divtab[16] = { +	      32, 16, 8, 8, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, +	    }; +	    fp->fftdropdiv[i] = divtab[fp->fftdata[i] / 2]; +	    fp->fftdata[i]--; +	  } +	} +      } +    } +  } +  for (int i = 0; i < FFTDISPLEN; i++) { +    fp->pacc.buf_rect( +        fp->pc, fp->buf_horizontal_7_d, +        SPECTRUM_X+i*4, SPECTRUM_Y-fp->fftdata[i]*2, 3, 1); +  } +  // level +  struct { +    unsigned level; +    int t; +    bool masked; +    uint8_t pan; +    uint8_t prog; +    uint8_t key; +    bool playing; +  } levels[FMDSP_LEVEL_COUNT] = {0}; +  for (int c = 0; c < 6; c++) { +    levels[c].level = leveldata_read(&fp->opna->fm.channel[c].leveldata); +    static const int table[4] = {5, 4, 0, 2}; +    levels[c].pan = table[fp->opna->fm.lselect[c]*2 + fp->opna->fm.rselect[c]]; +  } +  levels[0].t = FMDRIVER_TRACK_FM_1; +  levels[1].t = FMDRIVER_TRACK_FM_2; +  levels[2].t = FMDRIVER_TRACK_FM_3; +  levels[3].t = FMDRIVER_TRACK_FM_4; +  levels[4].t = FMDRIVER_TRACK_FM_5; +  levels[5].t = FMDRIVER_TRACK_FM_6; + +  for (int c = 0; c < 3; c++) { +    levels[6+c].level = leveldata_read(&fp->opna->resampler.leveldata[c]); +    levels[6+c].t = FMDRIVER_TRACK_SSG_1+c; +    levels[6+c].pan = 2; +  } +  { +    unsigned dl = 0; +    for (int d = 0; d < 6; d++) { +      unsigned l = leveldata_read(&fp->opna->drum.drums[d].leveldata); +      if (l > dl) dl = l; +    } +    levels[9].level = dl; +    levels[9].pan = 2; +  } +  levels[10].level = leveldata_read(&fp->opna->adpcm.leveldata); +  levels[10].t = FMDRIVER_TRACK_ADPCM; +  { +    static const int table[4] = {5, 4, 0, 2}; +    int ind = 0; +    if (fp->opna->adpcm.control2 & 0x80) ind |= 2; +    if (fp->opna->adpcm.control2 & 0x40) ind |= 1; +    levels[10].pan = table[ind]; +  } +  for (int p = 0; p < 8; p++) { +    levels[11+p].pan = 5; +    levels[11+p].t = FMDRIVER_TRACK_PPZ8_1+p; +  } +  if (fp->work->ppz8) { +    for (int p = 0; p < 8; p++) { +      levels[11+p].level = leveldata_read(&fp->work->ppz8->channel[p].leveldata); +      static const int table[10] = {5, 0, 1, 1, 1, 2, 3, 3, 3, 4}; +      levels[11+p].pan = table[fp->work->ppz8->channel[p].pan]; +    } +  } +  for (int c = 0; c < FMDSP_LEVEL_COUNT; c++) { +    levels[c].masked = c == 9 ? fp->masked_rhythm : fp->masked[levels[c].t]; +    levels[c].prog = fp->work->track_status[levels[c].t].tonenum; +    levels[c].key = fp->work->track_status[levels[c].t].key; +    levels[c].playing = fp->work->track_status[levels[c].t].playing; +    if (fp->work->track_status[levels[c].t].info == FMDRIVER_TRACK_INFO_PDZF || +        fp->work->track_status[levels[c].t].info == FMDRIVER_TRACK_INFO_PPZ8) { +      levels[c].playing = false; +    } +    if (!levels[c].playing) levels[c].pan = 5; +  } + +  for (int c = 0; c < FMDSP_LEVEL_COUNT; c++) { +    unsigned level = levels[c].level; +    unsigned llevel = 0; +    if (level) { +      float db = 20.0f * log10f((float)level / (1<<15)); +      float fllevel = (db / 48.0f + 1.0f) * 32.0f; +      if (fllevel > 0.0f) llevel = fllevel; +    } + +    if (fp->leveldata[c] <= llevel) { +      fp->leveldata[c] = llevel; +      fp->levelcnt[c] = 30; +    } else { +      if (fp->levelcnt[c]) { +        fp->levelcnt[c]--; +      } else { +        if (fp->leveldata[c]) { +          if (fp->leveldropdiv[c]) { +            fp->leveldropdiv[c]--; +          } else { +            static const uint8_t divtab[16] = { +              32, 16, 8, 8, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, +            }; +            fp->leveldropdiv[c] = divtab[fp->leveldata[c] / 2]; +            fp->leveldata[c]--; +          } +        } +      } +    } +    fp->pacc.buf_rect( +        fp->pc, fp->buf_horizontal_2_d, +        LEVEL_X + LEVEL_W*c, LEVEL_Y + (64-llevel*2), +        LEVEL_DISP_W, llevel*2); +    fp->pacc.buf_rect( +        fp->pc, fp->buf_horizontal_7_d, +        LEVEL_X + LEVEL_W*c, LEVEL_Y + (62-fp->leveldata[c]*2), +        LEVEL_DISP_W, 1); +    fp->pacc.buf_rect_off( +        fp->pc, levels[c].masked ? fp->buf_panpot_5_d : fp->buf_panpot_1_d, +        LEVEL_X + LEVEL_W*c-1, PANPOT_Y, +        PANPOT_W, PANPOT_H, +        0, PANPOT_H*levels[c].pan); +    if (c != 9) { +      fp->pacc.buf_printf( +          fp->pc, fp->buf_font_1_d, +          LEVEL_X + LEVEL_W*c, LEVEL_PROG_Y, +          "%03d", levels[c].prog); +    } +    uint8_t oct = levels[c].key >> 4; +    uint8_t n = levels[c].key & 0xf; +    if (c != 9 && levels[c].playing && n < 12) { +      fp->pacc.buf_printf( +          fp->pc, fp->buf_font_1_d, +          LEVEL_X + LEVEL_W*c, LEVEL_KEY_Y, +          "%03d", oct*12 + n); +    } else { +      fp->pacc.buf_printf( +          fp->pc, fp->buf_font_1_d, +          LEVEL_X + LEVEL_W*c, LEVEL_KEY_Y, +          "---"); +    } +  }  }  static void mode_update(struct fmdsp_pacc *fp) { +  fp->pacc.buf_clear(fp->buf_horizontal_3);    fp->pacc.buf_clear(fp->buf_font_1);    fp->pacc.buf_clear(fp->buf_font_2);    fp->pacc.buf_clear(fp->buf_font_7); @@ -1087,6 +1426,7 @@ static void mode_update(struct fmdsp_pacc *fp) {    fp->pacc.buf_clear(fp->buf_tri_7);    fp->pacc.buf_clear(fp->buf_tri);    fp->pacc.buf_clear(fp->buf_checker); +  fp->pacc.buf_clear(fp->buf_checker_1);    fp->pacc.buf_clear(fp->buf_curl_left);    fp->pacc.buf_clear(fp->buf_curl_right);    fp->pacc.buf_clear(fp->buf_play); @@ -1166,7 +1506,11 @@ void fmdsp_pacc_render(struct fmdsp_pacc *fp) {    fp->pacc.buf_clear(fp->buf_vertical_2);    fp->pacc.buf_clear(fp->buf_vertical_3);    fp->pacc.buf_clear(fp->buf_vertical_7); +  fp->pacc.buf_clear(fp->buf_horizontal_2_d); +  fp->pacc.buf_clear(fp->buf_horizontal_7_d);    fp->pacc.buf_clear(fp->buf_circle); +  fp->pacc.buf_clear(fp->buf_panpot_1_d); +  fp->pacc.buf_clear(fp->buf_panpot_5_d);    unsigned mask = 0;    if (fp->opna) {      mask = opna_get_mask(fp->opna); @@ -1232,22 +1576,29 @@ void fmdsp_pacc_render(struct fmdsp_pacc *fp) {    fp->pacc.draw(fp->pc, fp->buf_font_1, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_font_1_d, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_dt_sign, pacc_mode_color); +  fp->pacc.draw(fp->pc, fp->buf_checker_1, pacc_mode_color); +  fp->pacc.draw(fp->pc, fp->buf_panpot_1_d, pacc_mode_color);    fp->pacc.color(fp->pc, 3);    fp->pacc.draw(fp->pc, fp->buf_solid_3, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_solid_3_d, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_vertical_3, pacc_mode_color); +  fp->pacc.draw(fp->pc, fp->buf_horizontal_3, pacc_mode_color);    fp->pacc.color(fp->pc, 2);    fp->pacc.draw(fp->pc, fp->buf_font_2, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_font_2_d, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_solid_2, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_solid_2_d, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_vertical_2, pacc_mode_color); +  fp->pacc.draw(fp->pc, fp->buf_horizontal_2_d, pacc_mode_color); +  fp->pacc.color(fp->pc, 5); +  fp->pacc.draw(fp->pc, fp->buf_panpot_5_d, pacc_mode_color);    fp->pacc.color(fp->pc, 7);    fp->pacc.draw(fp->pc, fp->buf_font_7, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_solid_7, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_solid_7_d, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_vertical_7, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_tri_7, pacc_mode_color); +  fp->pacc.draw(fp->pc, fp->buf_horizontal_7_d, pacc_mode_color);    fp->pacc.draw(fp->pc, fp->buf_tri, pacc_mode_copy);    fp->pacc.draw(fp->pc, fp->buf_num, pacc_mode_copy);    fp->pacc.draw(fp->pc, fp->buf_checker, pacc_mode_copy); @@ -1289,9 +1640,10 @@ void fmdsp_pacc_render(struct fmdsp_pacc *fp) {    fp->framecnt++;  } -void fmdsp_pacc_set(struct fmdsp_pacc *fp, struct fmdriver_work *work, struct opna *opna) { +void fmdsp_pacc_set(struct fmdsp_pacc *fp, struct fmdriver_work *work, struct opna *opna, struct fmplayer_fft_input_data *idata) {    fp->work = work;    fp->opna = opna; +  fp->fftin = idata;  }  void fmdsp_pacc_palette(struct fmdsp_pacc *fp, int p) { diff --git a/fmdsp/fmdsp-pacc.h b/fmdsp/fmdsp-pacc.h index fb19b79..992a8eb 100644 --- a/fmdsp/fmdsp-pacc.h +++ b/fmdsp/fmdsp-pacc.h @@ -6,9 +6,11 @@ struct pacc_ctx;  struct pacc_vtable;  struct fmdriver_work work;  struct opna opna; +struct fmplayer_fft_input_data;  enum {    FMDSP_PALETTE_COLORS = 10, +  FMDSP_LEVEL_COUNT = 19,  };  enum { @@ -35,7 +37,7 @@ enum fmdsp_right_mode {  struct fmdsp_pacc *fmdsp_pacc_init(      struct pacc_ctx *pc, const struct pacc_vtable *vtable); -void fmdsp_pacc_set(struct fmdsp_pacc *pacc, struct fmdriver_work *work, struct opna *opna); +void fmdsp_pacc_set(struct fmdsp_pacc *pacc, struct fmdriver_work *work, struct opna *opna, struct fmplayer_fft_input_data *fftin);  void fmdsp_pacc_release(struct fmdsp_pacc *fp);  void fmdsp_pacc_render(struct fmdsp_pacc *fp); @@ -1,5 +1,6 @@  #include <SDL.h>  #include <stdbool.h> +#include <stdatomic.h>  #include "pacc/pacc.h"  #include "fmdsp/fmdsp-pacc.h"  #include "libopna/opna.h" @@ -7,6 +8,7 @@  #include "fmdriver/fmdriver.h"  #include "common/fmplayer_file.h"  #include "common/fmplayer_common.h" +#include "fft/fft.h"  bool loadgl(void); @@ -20,19 +22,29 @@ static struct {    struct opna_timer timer;    struct fmdriver_work work;    struct fmplayer_file *fmfile; +  struct fmplayer_fft_data fftdata; +  struct fmplayer_fft_input_data fftin;    const char *currpath;    SDL_Window *win;    SDL_AudioDeviceID adev;    struct ppz8 ppz8;    char adpcmram[OPNA_ADPCM_RAM_SIZE];    struct fmdsp_pacc *fp; -} g; +  atomic_flag fftdata_flag; +} g = { +  .fftdata_flag = ATOMIC_FLAG_INIT, +};  static void audiocb(void *ptr, Uint8 *bufptr, int len) {    int frames = len / (sizeof(int16_t)*2);    int16_t *buf = (int16_t *)bufptr;    memset(buf, 0, len);    opna_timer_mix(&g.timer, buf, frames); +  if (!atomic_flag_test_and_set_explicit( +        &g.fftdata_flag, memory_order_acquire)) { +    fft_write(&g.fftdata, buf, frames); +    atomic_flag_clear_explicit(&g.fftdata_flag, memory_order_release); +  }  }  static void openfile(const char *path) { @@ -57,6 +69,7 @@ static void openfile(const char *path) {  int main(int argc, char **argv) {    if (__builtin_cpu_supports("sse2")) opna_ssg_sinc_calc_func = opna_ssg_sinc_calc_sse2; +  fft_init_table();    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO)) {      SDL_Log("Cannot initialize SDL\n");      return 1; @@ -140,7 +153,7 @@ int main(int argc, char **argv) {      SDL_Quit();      return 1;    } -  fmdsp_pacc_set(g.fp, &g.work, &g.opna); +  fmdsp_pacc_set(g.fp, &g.work, &g.opna, &g.fftin);    SDL_EventState(SDL_DROPFILE, SDL_ENABLE); @@ -206,6 +219,11 @@ int main(int argc, char **argv) {          }        }      } +    if (!atomic_flag_test_and_set_explicit( +          &g.fftdata_flag, memory_order_acquire)) { +      memcpy(&g.fftin.fdata, &g.fftdata, sizeof(g.fftdata)); +      atomic_flag_clear_explicit(&g.fftdata_flag, memory_order_release); +    }      fmdsp_pacc_render(g.fp);      SDL_GL_SwapWindow(g.win);    } diff --git a/sdl/osx/Makefile b/sdl/osx/Makefile index 73bea70..8c17c7d 100644 --- a/sdl/osx/Makefile +++ b/sdl/osx/Makefile @@ -4,6 +4,7 @@ vpath %.c ../../fmdsp  vpath %.c ../../libopna  vpath %.c ../../common  vpath %.c ../../fmdriver +vpath %.c ../../fft  XCRUN:=xcrun --sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/  CC:=$(XCRUN) cc  OBJS:=main.o @@ -12,6 +13,7 @@ OBJS+=fmdsp-pacc.o font_fmdsp_small.o fmdsp_platform_unix.o  OBJS+=opna.o opnafm.o opnassg.o opnadrum.o opnaadpcm.o opnatimer.o opnassg-sinc-c.o opnassg-sinc-sse2.o  OBJS+=fmdriver_pmd.o fmdriver_fmp.o ppz8.o fmdriver_common.o  OBJS+=fmplayer_file.o fmplayer_work_opna.o fmplayer_file_unix.o fmplayer_drumrom_unix.o +OBJS+=fft.o  TARGET:=fmplayersdl  CFLAGS:=-Wall -Wextra -O2 -g  CFLAGS+=-DPACC_GL_3 diff --git a/sdl/unix/Makefile b/sdl/unix/Makefile index 9786031..ea22098 100644 --- a/sdl/unix/Makefile +++ b/sdl/unix/Makefile @@ -4,6 +4,7 @@ vpath %.c ../../fmdsp  vpath %.c ../../libopna  vpath %.c ../../common  vpath %.c ../../fmdriver +vpath %.c ../../fft  SDLCONFIG:=sdl2-config  OBJS:=main.o  OBJS+=pacc-gl.o @@ -11,6 +12,7 @@ OBJS+=fmdsp-pacc.o font_fmdsp_small.o fmdsp_platform_unix.o  OBJS+=opna.o opnafm.o opnassg.o opnadrum.o opnaadpcm.o opnatimer.o opnassg-sinc-c.o opnassg-sinc-sse2.o  OBJS+=fmdriver_pmd.o fmdriver_fmp.o ppz8.o fmdriver_common.o  OBJS+=fmplayer_file.o fmplayer_work_opna.o fmplayer_file_unix.o fmplayer_drumrom_unix.o +OBJS+=fft.o  TARGET:=fmplayersdl  CFLAGS:=-Wall -Wextra -O2 -g @@ -19,7 +21,7 @@ CFLAGS+=-DPACC_GL_3  #CFLAGS+=-DPACC_GL_ES -DPACC_GL_3  CFLAGS+=-I.. -I../..  CFLAGS+=$(shell $(SDLCONFIG) --cflags) -LIBS:=-lGL +LIBS:=-lGL -lm  LIBS+=$(shell $(SDLCONFIG) --libs)  $(TARGET):	$(OBJS) diff --git a/sdl/win/Makefile b/sdl/win/Makefile index e804dfc..0f63d19 100644 --- a/sdl/win/Makefile +++ b/sdl/win/Makefile @@ -4,6 +4,7 @@ vpath %.c ../../fmdsp  vpath %.c ../../libopna  vpath %.c ../../common  vpath %.c ../../fmdriver +vpath %.c ../../fft  SDLCONFIG:=i686-w64-mingw32-sdl2-config  CC:=i686-w64-mingw32-gcc  OBJS:=main.o @@ -12,6 +13,7 @@ OBJS+=fmdsp-pacc.o font_fmdsp_small.o fmdsp_platform_win.o  OBJS+=opna.o opnafm.o opnassg.o opnadrum.o opnaadpcm.o opnatimer.o opnassg-sinc-c.o opnassg-sinc-sse2.o  OBJS+=fmdriver_pmd.o fmdriver_fmp.o ppz8.o fmdriver_common.o  OBJS+=fmplayer_file.o fmplayer_work_opna.o fmplayer_file_win.o fmplayer_drumrom_win.o +OBJS+=fft.o  TARGET:=fmplayersdl.exe  CFLAGS:=-Wall -Wextra -O2 | 
