##実用性の低いFM音源用ボイスエディタ
対話式のYMF825用ボイスエディタ みたいなもの です。 でした。
追記追記 2017/9/17 再修正しました。キー操作を改善しました。
下記ソースからスクリーンエディット形式のボイスエディタを書きました。コード量が多いのでgithubにUPしております。
何分実機が無いので音を試すこともできません。やっていることはFM音源用ボイスエディタのために必要なバイト・ビット列を作ってみる 事だけ、です。一応hexダンプをしてみてサンプルコードのボイスデータと同じものになったので処理的には正しいのではないかと思います。ボイスエディタを作る為のツールのそのまた動作確認といった感じでしょうか。
作ったあとで、何もArduino上でやらなくてもコマンドラインアプリにしてターミナルで使えばよいのだと気が付きました。
FM音源への音設定が出来ないので、試しにeepromにデータを保存する様にしてみました。後々eepromへ保存された音データをプリセットトーンとしてYMF825へ設定して音を出す様なスケッチを書けば音源モジュールぽく使えるのではないかと考えています。
###使い方
p (リターン 以下同様)
全パラメータのプリント
op1,op2,op3,op4
パラメータ変更オペレータの選択。選択されているオペレータ番号がプロンプトに表示されます
?
パラメータ一覧
dmp
トーンデータのhexダンプ コピーペーストでソースコードに埋め込めます
sv
eepromへデータ保存
ld
eepromからデータ読出し
例:op2の SR(サスティンレイト)を2に設定するには
op2
sr 2
と入力します
シンセサイザのボイスエディタ系のソフトは昔からいくつか書いていますが、いつも似たような処理がダラダラ続いて本当に美しくないソースになってしまうのですよね。。。後々スクリーンエディタっぽく改良して実用に耐えるようにしたいと思います。
/*
* 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);
}