Arduino
FM音源

YMF825用 ボイスエディタみたいなもの

実用性の低いFM音源用ボイスエディタ

対話式のYMF825用ボイスエディタ みたいなもの です。 でした。


追記追記 2017/9/17 再修正しました。キー操作を改善しました。

下記ソースからスクリーンエディット形式のボイスエディタを書きました。コード量が多いのでgithubにUPしております。

https://github.com/ringoro/YMF825voiceeditor


何分実機が無いので音を試すこともできません。やっていることはFM音源用ボイスエディタのために必要なバイト・ビット列を作ってみる 事だけ、です。一応hexダンプをしてみてサンプルコードのボイスデータと同じものになったので処理的には正しいのではないかと思います。ボイスエディタを作る為のツールのそのまた動作確認といった感じでしょうか。
作ったあとで、何もArduino上でやらなくてもコマンドラインアプリにしてターミナルで使えばよいのだと気が付きました。

FM音源への音設定が出来ないので、試しにeepromにデータを保存する様にしてみました。後々eepromへ保存された音データをプリセットトーンとしてYMF825へ設定して音を出す様なスケッチを書けば音源モジュールぽく使えるのではないかと考えています。

使い方

p (リターン 以下同様)
全パラメータのプリント

op1,op2,op3,op4
パラメータ変更オペレータの選択。選択されているオペレータ番号がプロンプトに表示されます

?
パラメータ一覧

dmp
トーンデータのhexダンプ コピーペーストでソースコードに埋め込めます

sv
eepromへデータ保存

ld
eepromからデータ読出し

例:op2の SR(サスティンレイト)を2に設定するには

op2
sr 2

と入力します 

シンセサイザのボイスエディタ系のソフトは昔からいくつか書いていますが、いつも似たような処理がダラダラ続いて本当に美しくないソースになってしまうのですよね。。。後々スクリーンエディタっぽく改良して実用に耐えるようにしたいと思います。

LineFMEdit.ino
/*
 *    Voice Editor
 *   for YMF825 Tone
 * 
 *    2017/8/17
 *    Ringoro
 */

#include <avr/pgmspace.h>
#include <EEPROM.h>

int  inc=0;
int  rdc=0;
char inbuff[64];

struct ToneParams { 
  unsigned char boctv;
  unsigned char lfoalg;
  unsigned char op[4][7];
};


// defalut sample tone from github 
//   https://github.com/yamaha-webmusic/ymf825board

struct ToneParams toneparams ={
    0x01,0x85,
    0x00,0x7F,0xF4,0xBB,0x00,0x10,0x40,
    0x00,0xAF,0xA0,0x0E,0x03,0x10,0x40,
    0x00,0x2F,0xF3,0x9B,0x00,0x20,0x41,
    0x00,0xAF,0xA0,0x0E,0x01,0x10,0x40,
};   

char tname[16]="Default Tone";

// struct ToneParams toneparams;

int op=1;
char pt[8]="OP1>";

#define CR 0x0d

void setup() {
  Serial.begin(9600); 
}

int execstat(char *);

void loop() {
  char c;
  if (Serial.available() > 0) {
    c = Serial.read();
    Serial.print(c);
    inbuff[inc] = c;
    if(c==CR){
      inbuff[inc]=0;
      Serial.print("\n");
      Serial.println(inbuff); 
      execstat(inbuff);     // <= exec statement
      Serial.print(pt);
      inc=0;
    } else {inc = (inc+1) & 63;}

   }
}

/*
 * Execute Statment
 * 
 */

int execstat(char *s)
{
  int x;
  if(strstr(s,"op")){
    x = (int)*(s+2) - 0x30;
    if(x >=1 && x <=4){
      op=x;
    }
  }

  if(strstr(s,"dmp")){
    dumpparams();
    goto end;
  }

  if(strstr(s,"sv")){
    saveparams();
    goto end;
  }

  if(strstr(s,"ld")){
    loadparams();
    goto end;
  }


  if(strstr(s,"tn ")){
    setname(s);
    goto end;
  }


  if(strstr(s,"lfo ")){
    setlfo(s);
  }
  if(strstr(s,"alg ")){
    setalg(s);
  }
   if(strstr(s,"oct ")){
    setoct(s);
  }


  if(strstr(s,"ksr ")){
    setksr(s);
    goto end;
  }

  if(strstr(s,"sr ")){
    setsr(s);
    goto end;
  }


  if(strstr(s,"xof ")){
    setxof(s);
  }


  if(strstr(s,"rr ")){
    setrr(s);
  }
  if(strstr(s,"dr ")){
    setdr(s);
  }

  if(strstr(s,"ar ")){
    setar(s);
  }

  if(strstr(s,"ksl ")){
    setksl(s);
    goto end;
  }
  if(strstr(s,"sl ")){
    setsl(s);
    goto end;
  }

  if(strstr(s,"tl ")){
    settl(s);
  }

  if(strstr(s,"dam ")){
    setdam(s);
  }
  if(strstr(s,"eam ")){
    seteam(s);
  }
  if(strstr(s,"dvb ")){
    setdvb(s);
  }
  if(strstr(s,"evb ")){
    setevb(s);
  }

  if(strstr(s,"mlt ")){
    setmulti(s);
  }


  if(strstr(s,"dt ")){
    setdt(s);
  }

  if(strstr(s,"ws ")){
    setws(s);
  }

  if(strstr(s,"fb ")){
    setfb(s);
  }

  if(strstr(s,"p")){
    printparam();
  }

  if(strstr(s,"?")){
    printhelp();
  }

  end:
  sprintf(pt,"OP%d>",op);

  return 0;
}


/*
 * Set Params ...
 */

// LFO

int setlfo(char *s)
{
  int v;
  unsigned char lfoalg;
  s=s+4;
  sscanf(s,"%d",&v);
  lfoalg = toneparams.lfoalg & 0x03;
  lfoalg = lfoalg | v << 6;
  toneparams.lfoalg = lfoalg;
//  Serial.print(toneparams.lfoalg,HEX);
  return 0;
}

// ALG 

int setalg(char *s)
{
  int v;
  unsigned char lfoalg;
  s=s+4;
  sscanf(s,"%d",&v);
  lfoalg = toneparams.lfoalg & 0xC0;
  lfoalg = lfoalg | v ;
  toneparams.lfoalg = lfoalg;
//  Serial.print(toneparams.lfoalg,HEX);
  return 0;
}

int setname(char *s)
{
  int i;
  s=s+3;
  for(i=0;i<15;i++){
    tname[i]=*(s+i);
   }
  return 0;
}

// OCT Basic Octave

int setoct(char *s)
{
  int v;
  unsigned char oct;
  s=s+4;
  sscanf(s,"%d",&v);
  oct =  v & 0x03;
  toneparams.boctv = oct;
//  Serial.print(toneparams.boctv,HEX);
  return 0;
}

// SR 

int setsr(char *s)
{
  int v;
  unsigned char sr;
  s=s+3;
  sr = toneparams.op[op-1][0] & 0x0F; 

  sscanf(s,"%d",&v);
  sr = sr | (v & 0x0F) << 4;
  toneparams.op[op-1][0] =sr ;
//  Serial.print(toneparams.op[op-1][0],HEX);
  return 0;
}

// XOF

int setxof(char *s)
{
  int v;
  unsigned char xf;
  s=s+4;
  xf = toneparams.op[op-1][0] & 0b11110001;
  sscanf(s,"%d",&v);
   v = v & 1;
   xf = xf | ( v  << 3);
  toneparams.op[op-1][0] =xf ;
//  Serial.println(toneparams.op[op-1][0],HEX);
  return 0;
}

//  KSR

int setksr(char *s)
{
  int v;
  unsigned char ksr;
  s=s+4;
  ksr = toneparams.op[op-1][0] & 0b11111000;
  sscanf(s,"%d",&v);
   v = v & 1;
   ksr = ksr |  v ;
  toneparams.op[op-1][0] =ksr;
//  Serial.println(toneparams.op[op-1][0],HEX);
  return 0;
}

// RR 

int setrr(char *s)
{
  int v;
  unsigned char rr;
  s=s+3;
  rr = toneparams.op[op-1][1] & 0b00001111;
  sscanf(s,"%d",&v);
   v = (v & 0x0F) << 4;
   rr = rr |  v  ;
  toneparams.op[op-1][1] =rr;
//  Serial.println(toneparams.op[op-1][1],HEX);
  return 0;
}

//   DR

int setdr(char *s)
{
  int v;
  unsigned char rr;
  s=s+3;
  rr = toneparams.op[op-1][1] & 0b11110000;
  sscanf(s,"%d",&v);
   v = (v & 0x0F);
   rr = rr |  v  ;
  toneparams.op[op-1][1] =rr;
//  Serial.println(toneparams.op[op-1][1],HEX);
  return 0;
}

// AR

int setar(char *s)
{
  int v;
  unsigned char rr;
  s=s+3;
  rr = toneparams.op[op-1][2] & 0b00001111;
  sscanf(s,"%d",&v);
   v = (v & 0x0F) << 4;
   rr = rr |  v  ;
  toneparams.op[op-1][2] =rr;
  return 0;
}

// SL

int setsl(char *s)
{
  int v;
  unsigned char rr;
  s=s+3;
  rr = toneparams.op[op-1][2] & 0b11110000;
  sscanf(s,"%d",&v);
   v = (v & 0x0F);
   rr = rr |  v  ;
  toneparams.op[op-1][2] =rr;
  return 0;
}

// TTL  Total Level

int settl(char *s)
{
  int v;
  unsigned char rr;
  s=s+3;
  rr = toneparams.op[op-1][3] & 0b00000011;
  sscanf(s,"%d",&v);
   v = (v & 0b00111111) << 2;
   rr = rr |  v  ;
  toneparams.op[op-1][3] =rr;
  return 0;
}

//  KSL

int setksl(char *s)
{
  int v;
  unsigned char rr;
  s=s+4;
  rr = toneparams.op[op-1][3] & 0b11111100;
  sscanf(s,"%d",&v);
   v = (v & 0x3);
   rr = rr |  v  ;
  toneparams.op[op-1][3] =rr;
  return 0;
}

//    DAM

int setdam(char *s)
{
  int v;
  unsigned char rr;
  s=s+4;
  rr = toneparams.op[op-1][4] & 0b00011111;
  sscanf(s,"%d",&v);
   v = (v & 0x3);
   rr = rr |  v << 5 ;
  toneparams.op[op-1][4] =rr;
  return 0;
}

// EAM 

int seteam(char *s)
{
  int v;
  unsigned char rr;
  s=s+4;
  rr = toneparams.op[op-1][4] & 0b11101111;
  sscanf(s,"%d",&v);
   v = (v & 0x1);
   rr = rr |  v << 4 ;
  toneparams.op[op-1][4] =rr;
  return 0;
}


//  DVB

int setdvb(char *s)
{
  int v;
  unsigned char rr;
  s=s+4;
  rr = toneparams.op[op-1][4] & 0b11110001;
  sscanf(s,"%d",&v);
   v = (v & 0x3);
   rr = rr |  v << 1 ;
  toneparams.op[op-1][4] =rr;
  return 0;
}

//  EVB

int setevb(char *s)
{
  int v;
  unsigned char rr;
  s=s+4;
  rr = toneparams.op[op-1][4] & 0b11111110;
  sscanf(s,"%d",&v);
   v = (v & 0x1);
   rr = rr |  v  ;
  toneparams.op[op-1][4] =rr;
  return 0;
}

// MULTI

int setmulti(char *s)
{
  int v;
  unsigned char rr;
  s=s+4;
  rr = toneparams.op[op-1][5] & 0b00000111;
  sscanf(s,"%d",&v);
   v = (v & 0xF);
   rr = rr |  v << 4 ;
  toneparams.op[op-1][5] =rr;
  return 0;
}

// DT 

int setdt(char *s)
{
  int v;
  unsigned char rr;
  s=s+3;
  rr = toneparams.op[op-1][5] & 0b11110000;
  sscanf(s,"%d",&v);
   v = (v & 0x3);
   rr = rr |  v ;
  toneparams.op[op-1][5] =rr;
  return 0;
}

// WS

int setws(char *s)
{
  int v;
  unsigned char rr;
  s=s+3;
  rr = toneparams.op[op-1][6] & 0b00000111;
  sscanf(s,"%d",&v);
   v = (v & 0x1F);
   rr = rr |  v << 3 ;
  toneparams.op[op-1][6] =rr;
  return 0;
}

// FB

int setfb(char *s)
{
  int v;
  unsigned char rr;
  s=s+3;
  rr = toneparams.op[op-1][6] & 0b11111000;
  sscanf(s,"%d",&v);
   v = (v & 0x7);
   rr = rr |  v ;
  toneparams.op[op-1][6] =rr;
  return 0;
}


/*
 * Tone Parameter Help
 */
void printhelp(void)
{
Serial.print(F(" BO:0..3  LFO:0..3 ALG:0..7 \r\n\
 SR:0..15  XOF:0,1 KSR:0,1 \r\n\
 RR:0..15  DR:0..15\r\n\
 AR:0..15  SL:0..15\r\n\
 TL:0..63  KSL:0..3\r\n\
 DAM:0..3  EAM:0,1 DVB:0..3 EVB:0,1\r\n\
 MULTI:0..15  DT:0..3  WS:0..31  FB:0..7\r\n"));
}


/*  
 *   Dump Parameter Hex
 */
void dumpparams(void)
{
  char s[32];
  int i;
  Serial.println("------");
  sprintf(s,"0x%02X,0x%02X,",toneparams.boctv,toneparams.lfoalg);
  Serial.println(s);
  for(i=0;i<4;i++){
      sprintf(s,"0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,0x%02X,",
      toneparams.op[i][0],toneparams.op[i][1],toneparams.op[i][2],toneparams.op[i][3],toneparams.op[i][4],toneparams.op[i][5],toneparams.op[i][6]);
      Serial.println(s);
    }
  Serial.println("------");
}
/*
 *   Screen Disp
 */

void printparam(void)
{
  char s[64];

   unsigned char lfoalg;
  lfoalg=toneparams.lfoalg;
  sprintf(s,"LFO:%3d ALG:%3d OCT:%3d %s",lfoalg>>6,lfoalg&0x7,toneparams.boctv,tname);
   Serial.println(s);

  Serial.println(F("-------OP1---OP2---OP3---OP4--"));
  sprintf(s," SR: %4d  %4d  %4d  %4d",
  toneparams.op[0][0] >> 4,toneparams.op[1][0] >> 4,toneparams.op[2][0] >> 4,toneparams.op[3][0] >> 4);
  Serial.println(s);

  sprintf(s,"XOF: %4d  %4d  %4d  %4d",
  toneparams.op[0][0] >> 3&1,toneparams.op[1][0] >> 3 &1,toneparams.op[2][0] >> 3 &1 ,toneparams.op[3][0] >> 3&1);
  Serial.println(s);

  sprintf(s,"KSR: %4d  %4d  %4d  %4d",
  toneparams.op[0][0] &1,toneparams.op[1][0] &1,toneparams.op[2][0] &1 ,toneparams.op[3][0] &1);
  Serial.println(s);

  sprintf(s," RR: %4d  %4d  %4d  %4d",
  toneparams.op[0][1] >> 4,toneparams.op[1][1] >>4,toneparams.op[2][1] >>4 ,toneparams.op[3][1] >> 4);
  Serial.println(s);
  sprintf(s," DR: %4d  %4d  %4d  %4d",
  toneparams.op[0][1] & 0x0f,toneparams.op[1][1] &0x0F,toneparams.op[2][1] &0x0F ,toneparams.op[3][1]&0x0F);
  Serial.println(s);

  sprintf(s," AR: %4d  %4d  %4d  %4d",
  toneparams.op[0][2] >> 4,toneparams.op[1][2] >>4,toneparams.op[2][2] >>4 ,toneparams.op[3][2] >> 4);
  Serial.println(s);
  sprintf(s," SL: %4d  %4d  %4d  %4d",
  toneparams.op[0][2] & 0x0f,toneparams.op[1][2] &0x0F,toneparams.op[2][2] &0x0F ,toneparams.op[3][2]&0x0F);
  Serial.println(s);

  sprintf(s," TL: %4d  %4d  %4d  %4d",
  toneparams.op[0][3] >> 2,toneparams.op[1][3] >>2,toneparams.op[2][3] >>2 ,toneparams.op[3][3] >> 2);
  Serial.println(s);
  sprintf(s,"KSL: %4d  %4d  %4d  %4d",
  toneparams.op[0][3] & 0x03,toneparams.op[1][3] &0x03,toneparams.op[2][3] &0x03 ,toneparams.op[3][3]&0x03);
  Serial.println(s);

 sprintf(s,"DAM: %4d  %4d  %4d  %4d",
  toneparams.op[0][4] >>5,toneparams.op[1][4] >>5,toneparams.op[2][4] >>5 ,toneparams.op[3][4]>>5);
  Serial.println(s);

 sprintf(s,"EAM: %4d  %4d  %4d  %4d",
  (toneparams.op[0][4] & 0x10) >> 4,(toneparams.op[1][4]&0x10) >>4 ,(toneparams.op[2][4]&0x10)>>4 ,(toneparams.op[3][4]&0x10) >>4);
  Serial.println(s);

 sprintf(s,"DVB: %4d  %4d  %4d  %4d",
  (toneparams.op[0][4] & 0x06) >> 1,(toneparams.op[1][4]&0x06) >>1 ,(toneparams.op[2][4]&0x06)>>1 ,(toneparams.op[3][4]&0x06) >>1);
  Serial.println(s);

 sprintf(s,"EVB: %4d  %4d  %4d  %4d",
  toneparams.op[0][4] & 0x01 ,toneparams.op[1][4]&0x01 ,toneparams.op[2][4]&0x01 ,toneparams.op[3][4]&0x01);
  Serial.println(s);

 sprintf(s,"MLT: %4d  %4d  %4d  %4d",
  toneparams.op[0][5] >>4 ,toneparams.op[1][5]>>4 ,toneparams.op[2][5]>>4 ,toneparams.op[3][5]>>4);
  Serial.println(s);

 sprintf(s," DT: %4d  %4d  %4d  %4d",
  toneparams.op[0][5] &3 ,toneparams.op[1][5]&3 ,toneparams.op[2][5]&3 ,toneparams.op[3][5]&3);
  Serial.println(s);


 sprintf(s," WS: %4d  %4d  %4d  %4d",
  toneparams.op[0][6] >>3 ,toneparams.op[1][6]>>3 ,toneparams.op[2][6]>>3 ,toneparams.op[3][6]>>3);
  Serial.println(s);

 sprintf(s," FB: %4d  %4d  %4d  %4d",
  toneparams.op[0][5] &7 ,toneparams.op[1][5]&7 ,toneparams.op[2][5]&7 ,toneparams.op[3][5]&7);
  Serial.println(s);

}

// Save,Load Tone Prameter

void saveparams(void)
{
  EEPROM.put(0,toneparams);
  EEPROM.put(32,tname);

}
void loadparams(void)
{
  EEPROM.get(0,toneparams);
  EEPROM.get(32,tname);
}