SSブログ

ギターが優しく泣いている 3 (プログラム編)

変数とテーブルの説明だけで何かわからなくなってきました。時間を置くと本人が簡単に別人に変身してしまうので、開発時に作ったドキュメント(特になにげないメモ)を保存しておくことは本当に重要だと痛感します。それでも、めげずにプログラム本体の説明をします。
//*************************************************************
// 12弦ギターのシミュレート
// MPLAB Ver.5.25
// XC8 Ver2.10
//*************************************************************
    uint8_t t_no;
    uint8_t g_no;
    uint8_t s_no;
    uint8_t arpe_no;
    uint16_t tab;  //1bit:6(12)弦・・・12bit:1弦 
    uint16_t pattern[6];    
    uint8_t point;
    uint8_t dnib;
    uint8_t unib;

// CONFIG1
#pragma config IESO = ON    
#pragma config BOREN = ON    
#pragma config PWRTE = OFF  
#pragma config FOSC = INTOSC 
#pragma config FCMEN = OFF 
#pragma config MCLRE = ON   
#pragma config CP = OFF    
#pragma config CPD = OFF  
#pragma config WDTE = OFF 
#pragma config CLKOUTEN = ON  

// CONFIG2
#pragma config WRT = OFF  
#pragma config LVP = OFF    
#pragma config STVREN = ON   
#pragma config PLLEN = OFF    
#pragma config BORV = LO  

#define _XTAL_FREQ  32000000
#define ON      1
#define OFF     0

#define EF  0xF0  // EndFileを示す識別子
#define NP  0xF1  // NotPlayを示す識別子

#define T0COUT  206    // Timer0 100us:206
#define PRESCALE  4    // 100μs:4

//*************************************************************
 //割り込みルーチン 
//*************************************************************
void __interrupt () InterTimer( void ){
    //結局、タイマ0割り込みは使用しませんでした    
    if(INTCONbits.TMR0IF == 1){ 
        TMR0 = T0COUT;           //100us
        if(Task_SW >= 3) Task_SW = 0; 
        Task_SW++; 
              INTCONbits.TMR0IF = 0;
    }

   //タイマ1割り込み   
    if(PIR1bits.TMR1IF == 1){       
        TMR1H = 224;             //1ms timer
        TMR1L = 192;
        //T時間のカウントを行なう
        for( tcount = 0; tcount < 12; tcount++ ){
            // T bits 01:ON
            if((ST[tcount] & 0b11111111) == 0b00000100){ 
                timer[tcount]++;                
                if(timer[tcount] > tmrT[tcount]) {
                    ST[tcount] &= 0b11110011;
                    // T bits 10 up
                    ST[tcount] |= 0b00001000;      
                    timer[tcount] = 0;
                }
            }
        }

        //G時間のカウントを行なう
        for( gcount = 0; gcount < 12; gcount++ ){ 
           //G bits 01:ON
            if((ST[gcount] & 0b11111111) == 0b00011101){  
                timer[gcount]++;                   
                if(timer[gcount] > tmrG[gcount]) {
                    ST[gcount] &= 0b11001111;
                    // 01:up
                    ST[gcount] |= 0b00100000;      
                    timer[gcount] = 0;
                }    
            }
        }

        //S時間のカウントを行なう
        for(scount = 0; scount < 12; scount++ ){ 
            // S bits 01:ON
            if((ST[scount] & 0b11111111) == 0b01111110){  
                timer[scount]++;                
                if(timer[scount] > tmrS[scount]) {
                    ST[scount] &= 0b00111111;
                    // 01:up 
                    ST[scount] |= 0b10000000;      
                    timer[scount] = 0;
                }    
            }
        }
        PIR1bits.TMR1IF = 0;
    }    
}

//************************************************************* 
// メインルーチン 
//************************************************************* 
void main(void){
    OSCCONbits.SPLLEN = 1; // PLL X4
    OSCCONbits.IRCF = 0b1110; // IRCF 8MHz_HF
    OSCCONbits.SCS = 0; // INTOSC
    
    OSCSTATbits.T1OSCR = 0; // disabled
    OSCSTATbits.PLLR = 0; // 4XPLL disable
    OSCSTATbits.OSTS = 0; // intosc
    OSCSTATbits.HFIOFR = 0; // disabled
    OSCSTATbits.HFIOFL = 0; // not0.2percent_acc
    OSCSTATbits.MFIOFR = 0; // disabled
    OSCSTATbits.LFIOFR = 0; // dsiabled
    OSCSTATbits.HFIOFS = 0; // not0.5percent_acc

    OSCTUNEbits.TUN = 0;// factory-calibrated frequency
    // デジタルIOのみ
    ANSELA = 0b00000000 ;
    // RA1:out 他は適当    
    TRISA  = 0b00111100 ;   
    PORTA  = 0b00000000 ; // all L
    // すべてデジタルIO
    // MIDI系統のみ規定。他は適当。
    ANSELB = 0b00000000 ;   
    TRISB  = 0b00001110 ;   
    WPUB   = 0b00000000 ;  
    PORTB  = 0b00000000 ;  
    APFCON1bits.TXCKSEL = 1 ; //1:RB5 0:RB2
    APFCON0bits.RXDTSEL = 1 ; //1:RB2 0:RB1 
 
    //Timer0 init(今回未使用)
    prescaler = PRESCALE;
    if (prescaler == 0) {
            OPTION_REGbits.PSA = 1;
        } else {
            OPTION_REGbits.PSA = 0;
            OPTION_REGbits.PS  = prescaler - 1;
        } 
    OPTION_REGbits.TMR0CS = 0; //fosc/4
    OPTION_REGbits.TMR0SE = 0;
    INTCONbits.TMR0IE = 1;
    //INTCONbits.PEIE = 1;

    //Timer1 init
    T1CONbits.TMR1ON = 1; //有効にする
    T1CONbits.TMR1CS = 0; //fosc/4
    T1CONbits.T1CKPS = 0;  //prescaler 0:2^0
    TMR1H = 224; //1ms timer
    TMR1L = 192;
    PIE1bits.TMR1IE = 1;
    INTCONbits.PEIE = 1;

    //UART
    TXSTAbits.CSRC  = 0; // don't care
    TXSTAbits.TX9   = 0; // 8 bit
    TXSTAbits.TXEN  = 1; // enable
    TXSTAbits.SYNC  = 0; // 非同期モード
    TXSTAbits.SENDB = 0; // break
    TXSTAbits.BRGH  = 0; // Low
    TXSTAbits.TRMT  = 0; // TSR full
    TXSTAbits.TX9D  = 0;  
    
    //RCSTA
    RCSTAbits.SPEN  = 1;  // serial port enable
    RCSTAbits.RX9   = 0; // 8bit
    RCSTAbits.SREN  = 0; // don't care
    RCSTAbits.CREN  = 1; // enable
    RCSTAbits.ADDEN = 0; // don't care
    RCSTAbits.FERR  = 0; // disable
    RCSTAbits.OERR  = 0; // over run error
    RCSTAbits.RX9D  = 0; 

    BAUDCON = 0; //BRG16 0
    SPBRG  = 15; // ボーレートを31250bpsに設定
   
    INTCONbits.GIE = 1;
   // 9n : midi channel = 0;
    midi_ch = 0b10010000; 
 
  //ここから主動作のルーチンです。大まかな処理を説明すると
  // ①P[ ][ ] から演奏するギターコード、M[ ]で奏法を選択
  // ②Upストロークの場合は発音する順番を入れ替え
  // ③発音時間は奏法により異なる。
    while(1){
            uint8_t i;
            uint8_t j;

            if( P[0][measure] != EF ){
                // Level= 0:OFF 1:Down 2:Up 3-5:Arpe*
                Level = M[measure] ;      
                bass_flg = OFF;
                for(i = 0 ; i < 12 ;i++ ){
                    // Upストロークの時
                    if(Level == 2){
                        //発音順番を変更     
                        j = ~i - 0b11110100;
                        F[i] = code[ P[0][measure] ][j] ;
                        N[i] = open[j]; 
                    } else {   //Down,Arpe*の時
                        F[i] = code[ P[0][measure] ][i] ;
                        N[i] = open[i];  
                      }
                    // 発音タイミング生成
                    if( F[i] != NP ){  
                        string |= ( 1 << (uint16_t) i);
                        if(bass_flg == OFF){
                            bass_flg = ON;
                            //root音(bass)の決定
                            bass = i;  
                        }
                    }
                    ST[i] = 0;
                }
                
                switch( Level ){ 
                    case 1: // DownとUp
                    case 2:
                        Stroke();
                        break;

                    case 3: // Arpe1
                        arpe_cnt = 6;
                        Arpe1();
                        break;

                    case 4:  // Arpe2
                        Arpe2();
                        break;
                        
                    case 5:  // Arpe3
                        Arpe3();
                        break;

                    default:
                        break;
                }
                measure++;                
            } else{
                measure = 0;
            }
        }
}

//************************************************************* 
//各演奏パターンのルーチン 
//*************************************************************
void  Stroke(void){
// ①使用するテーブルはP[ ] [ ] と M[ ]です(Arpeとは異なる)。
// ②ST[ ]のフラグにより、T→G→Sの各12弦分のタイマーを作動。
// ③タイマー値を設定し、割り込みルーチンでカウントする。
// ④時間差をつけて12弦分の発音をおこなう
    while( string ){ //すべての弦を演奏した?
         for (t_no = 0;t_no < 12 ;t_no++){
            if((ST[t_no] & 0b11110011) == 0b00000000){
                //OFF?
                if((ST[t_no] & 0b11111111) == 0b00000000){
                    //tmrT_sw = ON
                    ST[t_no] |= 0b00000100; 
                    tmrT[t_no] = Tbl[t_no];
                }
                //Tタイマーアップ?
                if((ST[t_no] & 0b11111111) == 0b00001000){ 
                    if(F[t_no] != NP){
                        //N[]フレットの音階:12(6)弦目から記入 
                        note = F[t_no] + N[t_no] + capo;        
                        while(TXIF == 0);  // 送信可能?
                        TXREG = midi_ch;// ノートオン送信
                        while(TXIF == 0);  // 送信可能?
                        TXREG = note;     // 送信する
                        while(TXIF == 0);  // 送信可能?
                        TXREG = V[t_no]; // 送信する
                    }
                    ST[t_no] &= 0b11111100;
                    //Ttimerが完了
                    ST[t_no] |= 0b00001100;   
                    //tmrG_sw = ここではOFF;Gset 00→01
                    ST[t_no] |= 0b00000001;     
                }
            }
        }
        // G
        for (g_no = 0;g_no < 12 ;g_no++){      
            if((ST[g_no] & 0b11001111 ) == 0b00001101){
                //OFF?
                if((ST[g_no] & 0b11111111) == 0b00001101){ 
                    //tmrG_sw = ON;
                    ST[g_no] |= 0b00010000;    
                    tmrG[g_no] = Tbl[tmr];
                }
                //Gタイマーアップ?
                if((ST[g_no] & 0b11111111) == 0b00101101){ 
                    //g_no番目の弦の鳴動OFF(midiへOFF出力)
                    //Gtimerが完了
                    ST[g_no] |= 0b00110000;    
                    if(F[g_no] != NP){
                        note = F[g_no] + N[g_no];        
                        while(TXIF == 0);   // 送信可能?
                        TXREG = midi_ch;// ノートオン送信
                        while(TXIF == 0);  // 送信可能?
                        TXREG = note;     // 送信する
                        while(TXIF == 0);  // 送信可能?
                        TXREG = 0;          //  string.V[g_no] = 0
                    }
                    ST[g_no] &= 0b11111100;
                    //tmrS_sw = ここではOFF;Sset→10
                    ST[g_no] |= 0b00000010;     
                }
            }
        }
        for (s_no = 0;s_no < 12 ;s_no++){ // S     
            if(( ST[s_no] & 0b00111111 ) == 0b00111110){
                //OFF?
                if((ST[s_no] & 0b11111111) == 0b00111110){
                    // tmrS_sw = ON; 
                    ST[s_no] |= 0b01000000;
                    // 0ms    
                    tmrG[g_no] = Tbl[0];       

                }
                //Sタイマーアップ?
                if((ST[s_no] & 0b11111111) == 0b10111110){
                    //Stimerが完了;Tset→11
                    ST[s_no] |= 0b11111111;    
                    string &= ~(1 << s_no);
                   //13-16ビット目をマスク
                    string &= 0b0000111111111111; 
                }
            }    
        }       
    }
    
}

//*************************************************************
void  Arpe1(void){
// ①使用するテーブルはP[ ] [ ]とM[ ](Strokeとは異なる)と、CT[ ]。
// ②ST[ ]のフラグにより、T→G→Sの各12弦分のタイマーを作動。
// ③タイマー値を設定し、割り込みルーチンでカウントする。
// ④CT[ ]で示す時間差で各弦を発音する。

   //すべての弦を演奏した?    
    while( string ){ 
        //00:T 01:G 10:S 11:END
        for (t_no = 0;t_no < 12 ;t_no++){  // T
             if((ST[t_no] & 0b11110011) == 0b00000000){ 
                //OFF?    
                if((ST[t_no] & 0b11111111) == 0b00000000){
                    //tmrT_sw = ON
                    ST[t_no] |= 0b00000100; 
                    tmrT[t_no] = Tbl[ CT[t_no] ];
                }
                //Tタイマーアップ?
                if((ST[t_no] & 0b11111111) == 0b00001000){ 
                    //t_no番目の弦を鳴動(midiへ出力)
                    if(F[t_no] != NP){
                        //N[]フレットの音階:12(6)弦目から
                        note = F[t_no] + N[t_no] + capo;         
                        while(TXIF == 0);  // 送信可能?
                        TXREG = midi_ch;// ノートオン送信
                        while(TXIF == 0);  // 送信可能?
                        TXREG = note;     // 送信する
                        while(TXIF == 0);  // 送信可能?
                        TXREG = V[t_no]; // 送信する
                    }
                    ST[t_no] &= 0b11111100;
                    //Ttimerが完了
                    ST[t_no] |= 0b00001100;
                    //tmrG_sw = ここではOFF;Gset 00→01
                    ST[t_no] |= 0b00000001;     
                    }
                }
            }
        }

        // G
        for (g_no = 0;g_no < 12 ;g_no++){  
            if((ST[g_no] & 0b11001111 ) == 0b00001101){
                //OFF?
                if((ST[g_no] & 0b11111111) == 0b00001101){
                    //tmrG_sw = ON;
                    ST[g_no] |= 0b00010000;
                    //G時間は各弦共通    
                    tmrG[g_no] = Tbl[ 14 ]; 
                }
                //Gタイマーアップ?
                if((ST[g_no] & 0b11111111) == 0b00101101){ 
                    //g_no番目の弦の鳴動OFF(midiへOFF出力)
                    ST[g_no] |= 0b00110000;    //Gtimerが完了
                    if(F[g_no] != NP){
                        note = F[g_no] + N[g_no];        
                        while(TXIF == 0);   // 送信可能?
                        TXREG = midi_ch; // ノートオン送信
                        while(TXIF == 0);   // 送信可能?
                        TXREG = note;      // 送信する
                        while(TXIF == 0);   // 送信可能?
                        TXREG = 0;           //  string.V[g_no] = 0
                    }
                    ST[g_no] &= 0b11111100;
                    //tmrS_sw = ここではOFF;Sset→10
                    ST[g_no] |= 0b00000010;     
                }
            }
        }

        // S
        for (s_no = 0;s_no < 12 ;s_no++){ 
            if(( ST[s_no] & 0b00111111 ) == 0b00111110){
                //OFF?
                if((ST[s_no] & 0b11111111) == 0b00111110){
                    //tmrS_sw = ON; 
                    ST[s_no] |= 0b01000000;    
                    //S時間は無しに設定
                    tmrS[s_no] = Tbl[0]; 
                }
                //Sタイマーアップ?
                if((ST[s_no] & 0b11111111) == 0b10111110){ 
                    arpe_cnt--;
                    if(arpe_cnt == 0){
                        //if(ST[s_no] == 0b11111111)  
                        string &= ~(1 << s_no);
                        //13-16ビット目をマスク
                        string &= 0b0000111111111111; 
                    } else {
                        //Stimerが完了;Tset→11
                        ST[s_no] = 0b00000000;
                      }
                }
            }    
        }       
   }

//*************************************************************
void  Arpe2(void){
// ①使用するテーブルはP[ ] [ ](Arpe2の)とTap[ ]。
// ②ST[ ]のフラグにより、T→G→Sの各12弦分のタイマー作動。
// ③タイマー値を設定し、割り込みルーチンでカウントする。
// ④メモリ節約のため、Tap[ ]でG時間とS時間を規定している。

    // 発音タイミング生成
    for( arpe_no = 0 ; arpe_no < 12 ; arpe_no++ ){ 
        F[arpe_no] = P[arpe_no][measure];
        if( F[arpe_no] != NP ){  
            string |= ( 1 << (uint16_t) arpe_no); 
            N[arpe_no] = open[arpe_no];  
            ST[arpe_no] = 0;
            dnib = Tap[arpe_no][measure] & 0b00001111;
            unib = (Tap[arpe_no][measure] >> 4) & 0b00001111;
            tmrG[arpe_no] = Tbl[dnib];
            tmrS[arpe_no] = Tbl[unib]; 
        }
    }
    tab = string;
    for (t_no = 0;t_no < 12 ;t_no++){
        //演奏するフレットか?
        if((tab >> t_no) & 1){                     
            if(F[t_no] != NP){
                //N[]フレットの音階:12(6)弦目から記入
                note = F[t_no] + N[t_no] + capo;         
                while(TXIF == 0);   // 送信可能?
                TXREG = midi_ch; // ノートオン送信
                while(TXIF == 0);   // 送信可能?
                TXREG = note;      // 送信する
                while(TXIF == 0);   // 送信可能?
                TXREG = V[t_no];  // 送信する
            }
            //Tタイマーは処理済みにする
            ST[t_no] = 0b00001101;       
        }
    }
    while(string){
        for (g_no = 0;g_no < 12 ;g_no++){
            arpe_cnt = (uint16_t) g_no;
            //演奏するフレットか?
            if((tab >> arpe_cnt) & 1){
                //G                     
                if((ST[g_no] & 0b11001111) == 0b00001101){
                    //OFF?
                    if((ST[g_no] & 0b11111111) == 0b00001101){
                        //tmrG_sw = ON 
                        ST[g_no] |= 0b00010000;    
                    }
                    //Gタイマーアップ?
                    if((ST[g_no] & 0b11111111) == 0b00101101){ 
                        ST[g_no] |= 0b00110000;
                        if(F[g_no] != NP){
                            //N[]フレットの音階:12(6)弦目から記入
                            note = F[g_no] + N[g_no] + capo;         
                            while(TXIF == 0);   // 送信可能?
                            TXREG = midi_ch; // ノートオフ送信
                            while(TXIF == 0);   // 送信可能?
                            TXREG = note;      // 送信する
                            while(TXIF == 0);   // 送信可能?
                            TXREG = 0;           // 送信する
                        }
                        ST[g_no] &= 0b11111100;
                        //tmrS_sw = ここではOFF;Sset 01→10
                        ST[g_no] |= 0b00000010;   
                    }
                }
            }
        }
        // S
        for (s_no = 0;s_no < 12 ;s_no++){ 
            arpe_cnt = (uint16_t) s_no ;
            //演奏するフレットか?
            if((tab >> arpe_cnt) & 1){ 
                if(( ST[s_no] & 0b00111111 ) == 0b00111110){
                    //OFF?
                    if((ST[s_no] & 0b11111111) == 0b00111110){
                        //tmrS_sw = ON; 
                        ST[s_no] |= 0b01000000;
                    }
                    //Sタイマーアップ?
                    if((ST[s_no] & 0b11111111) == 0b10111110){ 
                        //Stimerが完了;Tset→11   
                        ST[s_no] |= 0b11111111;    
                        string &= ~(1 << s_no);
                        //13-16ビット目をマスク
                        string &= 0b0000111111111111; 
                      }
                }
            }
        }
    }
}

//*************************************************************
void  Arpe3(void){
// ①使用するテーブルはP[ ] [ ]とCT[ ]とpattern[ ]です。
// ②ST[ ]のフラグにより、T→G→Sの各12弦分のタイマーを作動。
// ③タイマー値を設定し、割り込みルーチンでカウントする。
// ④pattern[ ]で1ピッキングあたりの弦を順次に発音する。

    uint8_t t_no;
    uint8_t g_no;
    uint8_t s_no;
    uint8_t arpe_no;
    uint16_t tab;  //1bit目:6(12)弦・・・12bit目:1弦       

    //アルペジオのroot音の探索と順番カウンタ
    for(arpe_no = 0;arpe_no < 6; arpe_no++){ 
        tab = pattern[arpe_no];
        //4(7)弦から6(12)弦でroot音は?
        if( tab & 0b0000000000111111){ 
            tab &= 0b1111111111000000;
            //12弦であること
            tab |= (uint16_t) ( 0b000000011 << bass ); 
        }
        string = tab;
        tmr =   CT[arpe_no] ;    // TmrG[tmr]       
        
    for (t_no = 0;t_no < 12 ;t_no++){
        //演奏するフレットか?
        if((tab >> t_no) & 1){                
            if(F[t_no] != NP){
               //N[]フレットの音階:12(6)弦目から記入
                note = F[t_no] + N[t_no] + capo;         
                while(TXIF == 0);    // 送信可能?
                TXREG = midi_ch;  // ノートオン送信
                while(TXIF == 0);    // 送信可能?
                TXREG = note;       // 送信する
                while(TXIF == 0);    // 送信可能?
                TXREG = V[t_no];   // 送信する
            }
            //Tタイマーは処理済みとする
            ST[t_no] = 0b00001101;       
        }
    }
    while(string){
        for (g_no = 0;g_no < 12 ;g_no++){
            arpe_cnt = (uint16_t) g_no;
            //演奏するフレットか?
            if((tab >> arpe_cnt) & 1){
                //G
                if((ST[g_no] & 0b11001111) == 0b00001101){ 
                    //OFF?       
                    if((ST[g_no] & 0b11111111) == 0b00001101){ 
                        //tmrG_sw = ON
                        ST[g_no] |= 0b00010000; 
                        tmrG[g_no] = Tbl[tmr];     //
                    }
                    //Gタイマーアップ?
                    if((ST[g_no] & 0b11111111) == 0b00101101){ 
                        ST[g_no] |= 0b00110000;
                        if(F[g_no] != NP){
                            //N[]フレットの音階:12(6)弦目から記入
                            note = F[g_no] + N[g_no] + capo;           
                            while(TXIF == 0);   // 送信可能?
                            TXREG = midi_ch; // ノートオフ送信
                            while(TXIF == 0);   // 送信可能?
                            TXREG = note;      // 送信する
                            while(TXIF == 0);   // 送信可能?
                            TXREG = 0;           // 送信する
                        }
                        ST[g_no] &= 0b11111100;
                        //tmrS_sw = ここではOFF;Sset 01→10
                        ST[g_no] |= 0b00000010;   
                    }
                }
            }
        }
        for (s_no = 0;s_no < 12 ;s_no++){ // S
            arpe_cnt = (uint16_t) s_no ;
            //演奏するフレットか?
            if((tab >> arpe_cnt) & 1){ 
                if(( ST[s_no] & 0b00111111 ) == 0b00111110){
                    //OFF?
                    if((ST[s_no] & 0b11111111) == 0b00111110){
                         //tmrS_sw = ON;
                        ST[s_no] |= 0b01000000;
                    }
                    //Sタイマーアップ?
                    if((ST[s_no] & 0b11111111) == 0b10111110){
                        //Stimerが完了;Tset→11
                        ST[s_no] |= 0b11111111;    
                        string &= ~(1 << s_no);
                        //13-16ビット目をマスク
                        string &= 0b0000111111111111; 
                      }
                }
            }
        }
    }
}
}
//*************************************************************
■実は・・・・・
YouTubeの動画を見ていると、アップ/ダウン・ストロークの演奏の後にスライド・バーによる演奏が続いていたのでした。これもイントロに含まれますね。この部分のTAB譜を見ると、奇妙な記号が出てきます。これがスライド・ギター奏法をあらわすらしいです。今回はいろいろ試してみたのですが、同じような効果が実現できませんでした。ギターの音色も変えたほうが良さそうなので、しばらく研究してみることにします。

キーワードは、スライドバー 、 ボトルネック

余談ですが、スライド・バーをお酒の瓶のくびを切って自作したことがあります。あれはどこに行ったのだろう。でも、最近は専用のスライド・バーが安く買えるみたいです。
■感想
アップ・ダウンストロークの演奏ですが、DX7に接続してみたところ、弦と弦の間の時間差や12弦ギターの感じは少しはでているように思いました。ストロークの時間(G時間)を適切に調整して、S時間は0にしてやると、いい線まではいくかなと思いました。著作権の問題で、コード進行や実際の演奏音は出せませんが、各時間をリアルタイムに調整できればもっと楽しめるでしょう。
そして、アルペジオ演奏(Arpe1〜Arpe3)ですが、どれもこれも一長一短があるようです。おすすめしないのはArpe2グループで、参考のデータを見て「これは・・・」と感じたら多分正解です。普通の楽譜がコスパ最高と思えるでしょう。指使いをリアルに再現できるのはArpe3のほうです。何よりピッキングのタイミングが重要みたいです。プログラムを後から付け足して行く方法で仕上げたので、テーブルのデータがわかりづらくなってしまいました。
最後にもっとおもしろいようにするために以下のように改善を図っていこうと思います。
●変化を目で見えるようにする
●時間(T,G,S)・ノート信号・Volumeはロータリーエンコーダー(RE)などで操作して、連続で変化できるようにすること
●コード名やテンポ、ストロークなどはわかりやすく指定できること。
やはりピアノロールのようなグラフィカル画面でタイミングやノートを変化出来るようにしたほうが良い。

 
今日の作業はここまで。
食材店で眺めていたらコアントローの54度というのを見つけた。アブサン化したのと思ったら製菓用のらしかった。香りが大好きなコアントロ・サワーで乾杯。

**** 回路図が非公開になっていたので修正しました。*****

※このブログで書かれた内容によって生じた損害等の一切の責任を負いかねますので、予めご了承下さい。



nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。