2021.8.14 YMF-825を使いこなす2

前回のつづきです。

今回は、YMF-825のサンプルスケッチを用いて、様々な音を鳴らします。

サンプルスケッチは、GitHubに上がっていました。

下記を参考にしてください。

YMF-825サンプルスケッチ

このサンプルスケッチをArduinoNanoに書き込みます。

GitHubのフォルダーを開くと、下記のようなファイルが入っています。

この中の、sample1のプログラムを今回はいじります。

sample1のプログラムはこんな感じです。

/*
 Conditions only for Arduino UNO
   RST_N- Pin9   
   SS   - Pin10
   MOSI - Pin11
   MISO - Pin12
   SCK  - Pin13
 */
#include <SPI.h>
//0 :5V 1:3.3V
#define OUTPUT_power 0

// only for Arduino UNO
void set_ss_pin(int val) {
    if(val ==HIGH) PORTB |= (4);
    else PORTB &= ~(4);
}

// only for Arduino UNO
void set_rst_pin(int val) {
    if(val ==HIGH) PORTB |= (2);
    else PORTB &= ~(2);
}

void if_write(char addr,unsigned char* data,char num){
  char i;
  char snd;
    set_ss_pin(LOW);
    SPI.transfer(addr);
    for(i=0;i<num;i++){
      SPI.transfer(data[i]);    
    }
    set_ss_pin(HIGH);  
}

void if_s_write(char addr,unsigned char data){
  if_write(addr,&data,1);
}

unsigned char if_s_read(char addr){
  
    unsigned char rcv;
    
    set_ss_pin(LOW);    
    SPI.transfer(0x80|addr);
    rcv = SPI.transfer(0x00);
    set_ss_pin(HIGH);  
    return rcv;  
}

void init_825(void) {
   set_rst_pin(LOW);
   delay(1);
   set_rst_pin(HIGH);
   if_s_write( 0x1D, OUTPUT_power );
   if_s_write( 0x02, 0x0E );
   delay(1);
   if_s_write( 0x00, 0x01 );//CLKEN
   if_s_write( 0x01, 0x00 ); //AKRST
   if_s_write( 0x1A, 0xA3 );
   delay(1);
   if_s_write( 0x1A, 0x00 );
   delay(30);
   if_s_write( 0x02, 0x04 );//AP1,AP3
   delay(1);
   if_s_write( 0x02, 0x00 );
   //add
   if_s_write( 0x19, 0xF0 );//MASTER VOL
   if_s_write( 0x1B, 0x3F );//interpolation
   if_s_write( 0x14, 0x00 );//interpolation
   if_s_write( 0x03, 0x01 );//Analog Gain
   
   if_s_write( 0x08, 0xF6 );
   delay(21);
   if_s_write( 0x08, 0x00 );
   if_s_write( 0x09, 0xF8 );
   if_s_write( 0x0A, 0x00 );
   
   if_s_write( 0x17, 0x40 );//MS_S
   if_s_write( 0x18, 0x00 );
}

void set_tone(void){
  unsigned char tone_data[35] ={
    0x81,//header
    //T_ADR 0
    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,
    0x80,0x03,0x81,0x80,
  };
  
   if_s_write( 0x08, 0xF6 );
   delay(1);
   if_s_write( 0x08, 0x00 );
  
   if_write( 0x07, &tone_data[0], 35 );//write to FIFO
}

void set_ch(void){
   if_s_write( 0x0F, 0x30 );// keyon = 0
   if_s_write( 0x10, 0x71 );// chvol
   if_s_write( 0x11, 0x00 );// XVB
   if_s_write( 0x12, 0x08 );// FRAC
   if_s_write( 0x13, 0x00 );// FRAC  
}

void keyon(unsigned char fnumh, unsigned char fnuml){
   if_s_write( 0x0B, 0x00 );//voice num
   if_s_write( 0x0C, 0x54 );//vovol
   if_s_write( 0x0D, fnumh );//fnum
   if_s_write( 0x0E, fnuml );//fnum
   if_s_write( 0x0F, 0x40 );//keyon = 1  
}

void keyoff(void){
   if_s_write( 0x0F, 0x00 );//keyon = 0
}

void setup() {
  // put your setup code here, to run once:
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  set_ss_pin(HIGH);
 
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  SPI.setDataMode(SPI_MODE0);
  SPI.begin();

  init_825();
  set_tone();
  set_ch();
}

void loop() {
  // put your main code here, to run repeatedly:
  keyon(0x14,0x65);
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x11);
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x42);
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x5d);
  delay(500);
  keyoff();
  delay(200);
  keyon(0x24,0x17);
  delay(500);
  keyoff();
  delay(200);
}

正直、よくわからなかったので早速書込んでみました。

なおスピーカーは、YMF-825のSPに直接繋ぎます。

実際の動作が下記の動画になります。

ド、レ、ミ、フぁ、ソまでをずっと繰り返しているようです。

どうやら、このプログラムの一番下の、void loop内の処理で音階を演奏しているみたいですね。



void loop() {
  // put your main code here, to run repeatedly:
  keyon(0x14,0x65);    //ド
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x11);    //レ
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x42);       //ミ
  delay(500);
  keyoff();
  delay(200);
  keyon(0x1c,0x5d);    //ファ
  delay(500);
  keyoff();
  delay(200);
  keyon(0x24,0x17);        //ソ
  delay(500);
  keyoff();
  delay(200);
}

この、keyonの中の16進数の数時(0x14,0x65)が音階を決めているようです。でも、数字に連続性もないし、10進数に変換しても、周波数ではなさそう。

いろいろ調べてみたところ、しくみはよくわかりませんでしたが、EguchiKazuyuki様のQiitaのブログにて、ここに書き込む音階のデータが示されていました。これもデータが必ずしも正確とは限らないそうなので、参照はあくまで自己責任でおねがいします。

YMF825の音階パラメータについてhttps://qiita.com/KazuyukiEguchi/items/8e7192a0114250f8898f

なので、音階は取り合えずここから参照すれば使えそうです。(大変感謝申し上げます)

次に、音色です。

設定次第で、様々な音を出せるようで、ピアノ、ギターなど自由に作れます。

サンプルコード内の、void set_toneの中の、tonedata[35]の配列の数字で決めています。



void set_tone(void){
  unsigned char tone_data[35] ={
    0x81,//header
    //T_ADR 0
    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,
    0x80,0x03,0x81,0x80,
  };
  
   if_s_write( 0x08, 0xF6 );
   delay(1);
   if_s_write( 0x08, 0x00 );
  
   if_write( 0x07, &tone_data[0], 35 );//write to FIFO
}

この配列を変えることで音色を変更できそうです。

音色のサンプルスケッチは、Himagine様のブログを参考にさせていただきました。

ヤマハ提供サンプル(2)https://sites.google.com/site/himagine201206/home/arduino/ymf825/030

下記に転載させていただきます。感謝申し上げます。

変換済 tonedata.txt

/*
// GrandPiano
0x01,0x43,      // modify BO:0 -> BO:1
0x00,0x67,0xFF,0x9D,0x00,0x10,0x40,
0x21,0x33,0xE2,0xA3,0x00,0x50,0x00,
0x10,0x41,0xD3,0x88,0x01,0x10,0x00,
0x21,0x62,0xD4,0x02,0x01,0x10,0x00,
*/

/*
// E.Piano
0x01,0x45,      // modify BO:0 -> BO:1
0x51,0xC4,0xFB,0x8C,0x44,0x70,0x95,
0x10,0x82,0xFF,0x12,0x45,0x10,0x00,
0x11,0xB0,0xF1,0x49,0x44,0x10,0x02,
0x11,0x72,0xFF,0x10,0x41,0x10,0x00,
*/

/*
// TenorSax
0x01,0x45,      // modify BO:0 -> BO:1
0x01,0x03,0x70,0x16,0x44,0x10,0x0B,
0x00,0x92,0x70,0x3C,0x43,0x10,0x40,
0x01,0x03,0x70,0x22,0x44,0x10,0x4B,
*/

/*
// PickBass
0x02,0x43,      // modify BO:0 -> BO:2
0x21,0x37,0xF1,0x4E,0x44,0x10,0x05,
0x41,0x6B,0xC7,0x54,0x44,0x70,0x00,
0x21,0x69,0xF2,0x5E,0x44,0x20,0x00,
*/

/*
// TnklBell
0x01,0x45,      // modify BO:0 -> BO:1
0x30,0x46,0xF5,0x41,0x44,0xE0,0x03,
0x70,0x66,0xCE,0x2E,0x44,0x20,0x00,
0x20,0x26,0xC5,0x78,0x44,0x77,0x08,
0x40,0x55,0xFD,0x04,0x54,0x60,0x00,
*/

/*
// NewAgePd
0x01,0x45,      // modify BO:0 -> BO:1
0x31,0x3F,0xF0,0x98,0x44,0x70,0x0D,
0x40,0x47,0xF0,0x2E,0x44,0x50,0x00,
0x00,0x11,0x60,0x62,0x03,0x17,0x0E,
0x00,0x51,0x81,0x02,0x03,0x10,0x00,
*/

/*
// RimShot
0x00,0x45,
0x59,0x50,0xF0,0x14,0x44,0xC0,0x17,
0x79,0x77,0xF7,0x00,0x44,0xB0,0x00,
0x68,0x6A,0xF8,0x00,0x44,0xC0,0x00,
0x78,0x77,0xF7,0x00,0x44,0x70,0x10,
*/

/*
// Castanet
0x01,0x45,      // modify BO:0 -> BO:1
0x58,0x97,0xFF,0x08,0x44,0x70,0x0E,
0x59,0xF8,0xAF,0x00,0x44,0x50,0x30,
0x68,0x55,0xF0,0x9C,0x44,0x20,0x28,
0x98,0x9A,0xCA,0x50,0x44,0x50,0x00,
*/

ここには、GrandPiano  E.Piano  TenorSax  PickBass  TnklBell  NewAgePd  RimShot  Castanetの八種類の音源があり、これをコピペすることで音色を変えれそうです。

今日は、ここまで。

カテゴリーblog

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA