音を創るということ6(ソフト作成編)
プログラムの作成2回目です。おさらいのためにプログラムを見返していますが、もっと簡単にできないのかとか、出来るプログラマーだったら、〇〇指向とか〇〇プログラミングで見通しのよい作り方をするんだろうかとか、本当に余計なことを考えてしまいます。
■voiceパラメータのMAX値テーブル
//**************************************************************
//Table voice_max[165]
//**************************************************************
const uint8_t voice_max[165]={
99, // voice[0]= ; OP6_EG_RATE1
99, // voice[1]= ; OP6_EG_RATE2
99, // voice[2]= ; OP6_EG_RATE3
99, // voice[3]= ; OP6_EG_RATE4
99, // voice[4]= ; OP6_EG_LEVEL1
99, // voice[5]= ; OP6_EG_LEVEL2
99, // voice[6]= ; OP6_EG_LEVEL3
99, // voice[7]= ; OP6_EG_LEVEL4
99, // voice[8]= ; OP6_KEY_BOARD_LEVEL_SCALE_BREAK_POINT
99, // voice[9]= ; OP6_KEY_BOARD_LEVEL_SCALE_LEFT_DEPTH
99, // voice[10]= ; OP6_KEY_BOARD_LEVEL_SCALE_RIGHT_DEPTH
3, // voice[11]= ; OP6_KEY_BOARD_LEVEL_SCALE_LEFT_CURVE
3, // voice[12]= ; OP6_KEY_BOARD_LEVEL_SCALE_RIGHT_CURVE
7, // voice[13]= ; OP6_KEY_BOARD_RATE_SCALLING
3, // voice[14]= ; OP6_MOD SENSITIVITY_AMPLITUDE
7, // voice[15]= ; OP6_OPERATOR_KEY_VELOCITY_SENSITIVITY
99, // voice[16]= ; OP6_OPERATOR_OUTPUT_LEVEL
1, // voice[17]= ; OP6_OSCILLATOR_MODE
31, // voice[18]= ; OP6_OSCILLATOR_FREQUENCY_COARSE
99, // voice[19]= ; OP6_OSCILLATOR_FREQUENCY_FINE
14, // voice[20]= ; OP6_OSCILLATOR_DETUNE
99, // voice[21]= ; OP5_EG_RATE1
99, // voice[22]= ; OP5_EG_RATE2
99, // voice[23]= ; OP5_EG_RATE3
99, // voice[24]= ; OP5_EG_RATE4
99, // voice[25]= ; OP5_EG_LEVEL1
99, // voice[26]= ; OP5_EG_LEVEL2
99, // voice[27]= ; OP5_EG_LEVEL3
99, // voice[28]= ; OP5_EG_LEVEL4
99, // voice[29]= ; OP5_KEY_BOARD_LEVEL_SCALE_BREAK_POINT
99, // voice[30]= ; OP5_KEY_BOARD_LEVEL_SCALE_LEFT_DEPTH
99, // voice[31]= ; OP5_KEY_BOARD_LEVEL_SCALE_RIGHT_DEPTH
3, // voice[32]= ; OP5_KEY_BOARD_LEVEL_SCALE_LEFT_CURVE
3, // voice[33]= ; OP5_KEY_BOARD_LEVEL_SCALE_RIGHT_CURVE
7, // voice[34]= ; OP5_KEY_BOARD_RATE_SCALLING
3, // voice[35]= ; OP5_MOD SENSITIVITY_AMPLITUDE
7, // voice[36]= ; OP5_OPERATOR_KEY_VELOCITY_SENSITIVITY
99, // voice[37]= ; OP5_OPERATOR_OUTPUT_LEVEL
1, // voice[38]= ; OP5_OSCILLATOR_MODE
31, // voice[39]= ; OP5_OSCILLATOR_FREQUENCY_COARSE
99, // voice[40]= ; OP5_OSCILLATOR_FREQUENCY_FINE
14, // voice[41]= ; OP5_OSCILLATOR_DETUNE
99, // voice[42]= ; OP4_EG_RATE1
99, // voice[43]= ; OP4_EG_RATE2
99, // voice[44]= ; OP4_EG_RATE3
99, // voice[45]= ; OP4_EG_RATE4
99, // voice[46]= ; OP4_EG_LEVEL1
99, // voice[47]= ; OP4_EG_LEVEL2
99, // voice[48]= ; OP4_EG_LEVEL3
99, // voice[49]= ; OP4_EG_LEVEL4
99, // voice[50]= ; OP4_KEY_BOARD_LEVEL_SCALE_BREAK_POINT
99, // voice[51]= ; OP4_KEY_BOARD_LEVEL_SCALE_LEFT_DEPTH
99, // voice[52]= ; OP4_KEY_BOARD_LEVEL_SCALE_RIGHT_DEPTH
3, // voice[53]= ; OP4_KEY_BOARD_LEVEL_SCALE_LEFT_CURVE
3, // voice[54]= ; OP4_KEY_BOARD_LEVEL_SCALE_RIGHT_CURVE
7, // voice[55]= ; OP4_KEY_BOARD_RATE_SCALLING
3, // voice[56]= ; OP4_MOD SENSITIVITY_AMPLITUDE
7, // voice[57]= ; OP4_OPERATOR_KEY_VELOCITY_SENSITIVITY
99, // voice[58]= ; OP4_OPERATOR_OUTPUT_LEVEL
1, // voice[59]= ; OP4_OSCILLATOR_MODE
31, // voice[60]= ; OP4_OSCILLATOR_FREQUENCY_COARSE
99, // voice[61]= ; OP4_OSCILLATOR_FREQUENCY_FINE
14, // voice[62]= ; OP4_OSCILLATOR_DETUNE
99, // voice[63]= ; OP3_EG_RATE1
99, // voice[64]= ; OP3_EG_RATE2
99, // voice[65]= ; OP3_EG_RATE3
99, // voice[66]= ; OP3_EG_RATE4
99, // voice[67]= ; OP3_EG_LEVEL1
99, // voice[68]= ; OP3_EG_LEVEL2
99, // voice[69]= ; OP3_EG_LEVEL3
99, // voice[70]= ; OP3_EG_LEVEL4
99, // voice[71]= ; OP3_KEY_BOARD_LEVEL_SCALE_BREAK_POINT
99, // voice[72]= ; OP3_KEY_BOARD_LEVEL_SCALE_LEFT_DEPTH
99, // voice[73]= ; OP3_KEY_BOARD_LEVEL_SCALE_RIGHT_DEPTH
3, // voice[74]= ; OP3_KEY_BOARD_LEVEL_SCALE_LEFT_CURVE
3, // voice[75]= ; OP3_KEY_BOARD_LEVEL_SCALE_RIGHT_CURVE
7, // voice[76]= ; OP3_KEY_BOARD_RATE_SCALLING
3, // voice[77]= ; OP3_MOD SENSITIVITY_AMPLITUDE
7, // voice[78]= ; OP3_OPERATOR_KEY_VELOCITY_SENSITIVITY
99, // voice[79]= ; OP3_OPERATOR_OUTPUT_LEVEL
1, // voice[80]= ; OP3_OSCILLATOR_MODE
31, // voice[81]= ; OP3_OSCILLATOR_FREQUENCY_COARSE
99, // voice[82]= ; OP3_OSCILLATOR_FREQUENCY_FINE
14, // voice[83]= ; OP3_OSCILLATOR_DETUNE
99, // voice[84]= ; OP2_EG_RATE1
99, // voice[85]= ; OP2_EG_RATE2
99, // voice[86]= ; OP2_EG_RATE3
99, // voice[87]= ; OP2_EG_RATE4
99, // voice[88]= ; OP2_EG_LEVEL1
99, // voice[89]= ; OP2_EG_LEVEL2
99, // voice[90]= ; OP2_EG_LEVEL3
99, // voice[91]= ; OP2_EG_LEVEL4
99, // voice[92]= ; OP2_KEY_BOARD_LEVEL_SCALE_BREAK_POINT
99, // voice[93]= ; OP2_KEY_BOARD_LEVEL_SCALE_LEFT_DEPTH
99, // voice[94]= ; OP2_KEY_BOARD_LEVEL_SCALE_RIGHT_DEPTH
3, // voice[95]= ; OP2_KEY_BOARD_LEVEL_SCALE_LEFT_CURVE
3, // voice[96]= ; OP2_KEY_BOARD_LEVEL_SCALE_RIGHT_CURVE
7, // voice[97]= ; OP2_KEY_BOARD_RATE_SCALLING
3, // voice[98]= ; OP2_MOD SENSITIVITY_AMPLITUDE
7, // voice[99]= ; OP2_OPERATOR_KEY_VELOCITY_SENSITIVITY
99, // voice[100]= ; OP2_OPERATOR_OUTPUT_LEVEL
1, // voice[101]= ; OP2_OSCILLATOR_MODE
31, // voice[102]= ; OP2_OSCILLATOR_FREQUENCY_COARSE
99, // voice[103]= ; OP2_OSCILLATOR_FREQUENCY_FINE
14, // voice[104]= ; OP2_OSCILLATOR_DETUNE
99, // voice[105]= ; OP1_EG_RATE1
99, // voice[106]= ; OP1_EG_RATE2
99, // voice[107]= ; OP1_EG_RATE3
99, // voice[108]= ; OP1_EG_RATE4
99, // voice[109]= ; OP1_EG_LEVEL1
99, // voice[110]= ; OP1_EG_LEVEL2
99, // voice[111]= ; OP1_EG_LEVEL3
99, // voice[112]= ; OP1_EG_LEVEL4
99, // voice[113]= ; OP1_KEY_BOARD_LEVEL_SCALE_BREAK_POINT
99, // voice[114]= ; OP1_KEY_BOARD_LEVEL_SCALE_LEFT_DEPTH
99, // voice[115]= ; OP1_KEY_BOARD_LEVEL_SCALE_RIGHT_DEPTH
3, // voice[116]= ; OP1_KEY_BOARD_LEVEL_SCALE_LEFT_CURVE
3, // voice[117]= ; OP1_KEY_BOARD_LEVEL_SCALE_RIGHT_CURVE
7, // voice[118]= ; OP1_KEY_BOARD_RATE_SCALLING
3, // voice[119]= ; OP1_MOD SENSITIVITY_AMPLITUDE
7, // voice[120]= ; OP1_OPERATOR_KEY_VELOCITY_SENSITIVITY
99, // voice[121]= ; OP1_OPERATOR_OUTPUT_LEVEL
1, // voice[122]= ; OP1_OSCILLATOR_MODE
31, // voice[123]= ; OP1_OSCILLATOR_FREQUENCY_COARSE
99, // voice[124]= ; OP1_OSCILLATOR_FREQUENCY_FINE
14, // voice[125]= ; OP1_OSCILLATOR_DETUNE
99, // voice[126]= ; PITCH_EG_RATE1
99, // voice[127]= ; PITCH_EG_RATE2
99, // voice[128]= ; PITCH_EG_RATE3
99, // voice[129]= ; PITCH_EG_RATE4
99, // voice[130]= ; PITCH_EG_LEVEL1
99, // voice[131]= ; PITCH_EG_LEVEL2
99, // voice[132]= ; PITCH_EG_LEVEL3
99, // voice[133]= ; PITCH_EG_LEVEL4
31, // voice[134]= ; ALGORITHM_SELECT
7, // voice[135]= ; FEED_BACK
1, // voice[136]= ; OSCILLATOR_SYNC
99, // voice[137]= ; LFO_SPEED
99, // voice[138]= ; LFO_DELAY
99, // voice[139]= ; LFO_PMD
99, // voice[140]= ; LFO_AMD
1, // voice[141]= ; LFO_SYNC
4, // voice[142]= ; LFO_WAVE
7, // voice[143]= ; MOD_SENSITIVITY_PITCH
48, // voice[144]= ; TRANSPOSE
0x7f, // voice[145]= ; VOICE_NAME1
0x7f, // voice[146]= ; VOICE_NAME2
0x7f, // voice[147]= ; VOICE_NAME3
0x7f, // voice[148]= ; VOICE_NAME4
0x7f, // voice[149]= ; VOICE_NAME5
0x7f, // voice[150]= ; VOICE_NAME6
0x7f, // voice[151]= ; VOICE_NAME7
0x7f, // voice[152]= ; VOICE_NAME8
0x7f, // voice[153]= ; VOICE_NAME9
0x7f, // voice[154]= ; VOICE_NAME10
0x3F, // voice[155]= ; OPERATOR_ON/OFF
// D6:0 D5:OP1 D4:OP2 D3:OP3 D2:OP4 D1:OP5 D0:OP6
//以降はこの機器用のパラメータ
5, // voice[156] ;selectされたOPナンバー op1:5 op6:0
1, // voice[157] ;OP6
1, // voice[158] ;OP5
1, // voice[159] ;OP4
1, // voice[160] ;OP3
1, // voice[161] ;OP2
1, // voice[162] ;OP1
99, // voice[163] ;None
99, // voice[164] ;None
};
//**************************************************************
●DX7の取扱説明書の31ページに載っている各パラメータのMAX値をテーブルにしています。右回しでMAXで止めるようにしています。左回し一杯はもちろん0です。
●パラメータの156番以降はこの装置内だけで使用するために追加しました。パラメータ163と164は、レイアウト図の上から4個目、左から2個目RE用です。今回は使用していませんが、メニュー切り替え用に利用しようとしています。パラメータ157〜162もOPの操作用に確保したのですが、今のところ予定なしです。
●コメントが途切れていますが、取扱説明書を丸写ししただけです。
●パラメータの156番以降はこの装置内だけで使用するために追加しました。パラメータ163と164は、レイアウト図の上から4個目、左から2個目RE用です。今回は使用していませんが、メニュー切り替え用に利用しようとしています。パラメータ157〜162もOPの操作用に確保したのですが、今のところ予定なしです。
●コメントが途切れていますが、取扱説明書を丸写ししただけです。
■voice初期データのテーブル
//*************************************************************
// Table voice_init[165 ] voice初期データ
//*************************************************************
const uint8_t voice_init[165]={
0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x63,0x63,0x63,
0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x01,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,
0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,
0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x63,0x63,
0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x63,0x63,0x63,0x63,0x63,
0x63,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,
0x00,0x01,0x00,0x00,0x63,0x63,0x63,0x63,0x32,0x32,0x32,0x32,
0x00,0x00,0x01,0x23,0x00,0x00,0x00,0x01,0x00,0x03,0x18,0x20,
0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3F, 0, 1, 1, 1,
1, 1, 1, 0, 0,
};
//*************************************************************
●電源投入時の最初のデータです。これをベースに設定値を書き換えていくのですが、電源投入時にDX7からのデータを受け付ければもっと音作りが楽になりそう。
●voice_maxとかvoice_initとかパラメータのデータが多いです。構造体を使えばもっとすっきりした形になるのだろうと思いつつ、最初の設計が試行錯誤で進んでいるので仕方ないね。開発初期段階の設計は本当に重要なのですよ。
●実はこのデータはDX7の初期時のデータを参考にしています。こういうデータは著作権に関係するのかなとファイル名だけは変えましたけど。
●voice_maxとかvoice_initとかパラメータのデータが多いです。構造体を使えばもっとすっきりした形になるのだろうと思いつつ、最初の設計が試行錯誤で進んでいるので仕方ないね。開発初期段階の設計は本当に重要なのですよ。
●実はこのデータはDX7の初期時のデータを参考にしています。こういうデータは著作権に関係するのかなとファイル名だけは変えましたけど。
■リングバッファ
//*************************************************************
// write_buff( ) と Read_buff( )
//*************************************************************
#define MAX 256
uint8_t data3;
uint8_t data4;
void write_buff(uint8_t data3){
if(!(rd_index == (wr_index+1) % MAX)){
buff[wr_index++] = data3;
if(wr_index == MAX) wr_index = 0;
}
}
uint8_t Read_buff(void){
if(!(rd_index == wr_index)){
data4 = buff[rd_index];
++ rd_index;
}
if(rd_index == MAX) rd_index = 0;
return data4;
}
//*************************************************************
●間違いを発見しました。write_buff は小文字なのに Read_buff は大文字でした。そのまま行きます。
●入力は割り込みで行っているので、メインルーチンの処理ではバッファが必要です。MAXが256では短いかなと思ってます。
●リングバッファをもうひとつ作っていました。詳細はこの下を見てください。
●入力は割り込みで行っているので、メインルーチンの処理ではバッファが必要です。MAXが256では短いかなと思ってます。
●リングバッファをもうひとつ作っていました。詳細はこの下を見てください。
■ main()
//*************************************************************
void main(void){
//OSC_init();
OSCCONbits.IRCF = 7; // 8MHz
OSCTUNEbits.PLLEN = 1; // PLL(x6)
OSCCONbits.SCS = 0;
//IO_init();
// 0が出力、1が入力
TRISA = 0b00010000;
TRISB = 0b10001111;
UCONbits.USBEN = 0;
UCFGbits.UTRDIS = 1;
TRISC = 0b11111000;
// 0がアナログ、1がデジタル
ANCON0 = 0b11111111;
ANCON1 = 0b00011111;
INTCON2bits.RBPU = 0;
RPINR16 = 10;
RPOR9 = 6;
// PRESCALE(0-8):6
T0CONbits.TMR0ON = 1;
T0CONbits.T08BIT = 1; // 8-bit timer
T0CONbits.T0CS = 0; // use internal-OSC
if (PRESCALE == 0) {
T0CONbits.PSA = 1; // Not use prescaler
} else {
T0CONbits.PSA = 0; // use prescaler
T0CONbits.T0PS = PRESCALE - 1;
}
TMR0 = T0COUT; //T0COUT=181
INTCONbits.TMR0IE = 1;
INTCONbits.TMR0IF = 0;
INTCON2bits.TMR0IP = 0;
INTCONbits.PEIE = 1;
rmidi_index = 0;
tmidi_index = 0;
LATA = 0b11101111;
LATC = 0b00000111;
LATB = 0b00110000;
//UART_Initialize();
TXSTA2bits.SYNC = 0;
TXSTA2bits.BRGH = 0;
TXSTA2bits.TXEN = 1;
TXSTA2bits.TX9 = 0;
RCSTA2bits.SPEN = 1;
RCSTA2bits.RX9 = 0;
RCSTA2bits.CREN = 1;
BAUDCON2bits.BRG16 = 0;
BAUDCON2bits.RXDTP = 0;
BAUDCON2bits.TXCKP = 0;
SPBRG2 = 23 ; // ボーレートを31250bpsに設定
INTCONbits.PEIE = 1;
INTCONbits.GIE = 1;
//Init_buff(); //初期データを編集バッファへ転送
for(bufno = 0;bufno < 165; bufno++){
edit_voice[bufno] = voice_init[bufno];
}
SelectNo = voice_init[156]; //voiceNoにOP1をセット
while(1){
In_oprate();
DX7_task();
}
}
//**************************************************************
●メインの前半は初期設定です。特別なことは何もしていません。
●編集で使うvoice_edit[ ]に初期データ voice_init[ ]を転送します。これがないと操作時に微妙に苦労するのです。
●後半は無限ループで回していますが、スイッチ(SW)とロータリーエンコーダ(RE)の処理を行なうIn_oprate() と、 実際の動作を行なうDX7_task()で構成しています。
●編集で使うvoice_edit[ ]に初期データ voice_init[ ]を転送します。これがないと操作時に微妙に苦労するのです。
●後半は無限ループで回していますが、スイッチ(SW)とロータリーエンコーダ(RE)の処理を行なうIn_oprate() と、 実際の動作を行なうDX7_task()で構成しています。
■DX7_task( )
//**************************************************************
// DX7_task( )
//**************************************************************
void DX7_task(void ){
taskloop = paramcount;
for(i = 0;i < taskloop; i++){
midichar[i] = Read_midibuff();
while(TX2IF == 0);
TXREG2 = midichar[i];
}
}
//**************************************************************
uint8_t midi_modify[7]={0xf0,0x43,0b00010000,00,00,00,0xf7};
void StoreMidi(void){
uint8_t add1;
uint8_t add2;
uint8_t i;
add2 = param & 0b01111111;
add1 = (param >> 7) & 0b00000011;
midi_modify[3] = add1;
midi_modify[4] = add2;
midi_modify[5] = data;
for(i = 0;i < 7; i++){
Write_midibuff(midi_modify[i]);
}
}
//**************************************************************
void Write_midibuff(uint8_t data1){
if(!(rmidi_index == (tmidi_index + 1) % MAX)){
midibuff[tmidi_index++] = data1;
if(tmidi_index == MAX) tmidi_index = 0;
}
}
uint8_t Read_midibuff(void){
if(!(rmidi_index == tmidi_index)){
data2 = midibuff[rmidi_index];
++ rmidi_index;
}
if(rmidi_index == MAX) rmidi_index = 0;
return data2;
}
//**************************************************************
●さり気なく、Write_midibuff とか Read_midibuff とかの関数を書いていますが、リングバッファはパラメータ入力用とこのmidi用の2種類あったのでした。
■SW・REの入力処理
//**************************************************************
// In_oprate
//**************************************************************
void In_oprate(void){
uint8_t tmp;
uint8_t p;
uint8_t row; //行
uint8_t column; //列
uint8_t count;
uint8_t swcnt;
uint8_t swand;
uint8_t swnum;
uint8_t padr;
for(swcnt=0;swcnt < 2;swcnt++ ){
op_flag_old = op_flag;
swand = And[swcnt];
for(swnum = 0 ;swnum < 8 ;swnum = swnum + 2){
if(swcnt == 0 ){
//ONの処理
if((swand >> swnum) & 0b00000001){
op_flag |= (0b00001000 >> (swnum >> 1));
} else {
//OFFの処理
op_flag &= ~(0b00001000 >> (swnum >> 1));
}
}
if(swcnt == 1 && swnum > 3 ){
if((swand >> swnum) & 0b00000001 ){ //ONの処理
if(swnum == 4){
op_flag |= 0b00100000; //ch_no= 1 bit= 4,6
}
if(swnum == 6){
op_flag |= 0b00010000;
}
} else { //OFFの処理
if(swnum == 4){
op_flag &= ~(0b00100000);
}
if(swnum == 6){
op_flag &= ~(0b00010000);
}
}
}
}
if(op_flag ^ op_flag_old){
padr = 155;
edit_voice[155] = op_flag;
param = padr;
data = edit_voice[padr];
StoreMidi();
}
}
INTCONbits.TMR0IE = 0; //TMR0 disable
ch_no = Read_buff();
Rot_R = Read_buff();
Exor = Read_buff();
INTCONbits.TMR0IE = 1; //TMR0 enable
for(count = 0 ;count < 8;count = count + 2){
if(ch_no == 0 ||( ch_no == 1 && count > 3)) continue;
if((Exor >> count) & 0b00000001){
if((Rot_R >> count) & 0b00000001){
boundry[ch_no] |= (0b00000001 << count);
if(((Rot_R >> count) >> 1) & 0b00000001 ){
cw_ccw[ch_no] |= (0b00000010 << count);
} else {
cw_ccw[ch_no] |= (0b00000001 << count);
}
} else { //立ち下がり
boundry[ch_no] |= (0b00000001 << (count + 1));
if(((Rot_R >> count) >> 1) & 0b00000001 ){
cw_ccw[ch_no] |= (0b00000001 << count);
} else {
cw_ccw[ch_no] |= (0b00000010 << count);
}
}
}
}
for(column = 0;column < 8 ;column =column + 2) {
//いずれかの入力に変化があったら
if(boundry[ch_no]){
p=0;
if(ch_no > 5){ //row=6,7,8,9,10,11
SelectNo = edit_voice[156]; //OP1-OP6を選択
p = SelectNo * 21;
if(ch_no == 6) {
if( column > 4) p = 0;
}
if((ch_no == 8) && (column > 6)) p = 0;
}
padr = no[ch_no][column] + p;
Rotcnt[column] = edit_voice[padr];
if(((boundry[ch_no] >> column) & 0b00000011) == 1){
//CW
if(((cw_ccw[ch_no] >> column) & 0b00000011) == 1){
Rotcnt[column]++;
if(Rotcnt[column] > voice_max[padr]) {
Rotcnt[column] = voice_max[padr];
}
}
//CCW
if(((cw_ccw[ch_no] >> column) & 0b00000011) == 2){
Rotcnt[column]--;
if(Rotcnt[column] > voice_max[padr] ) {
Rotcnt[column] = 0;
}
}
if(edit_voice[padr] ^ Rotcnt[column]){
edit_voice[padr] = Rotcnt[column];
timerstart = 1; //次の入力があるとタイマーを
periodtimer = 0; //リセットし、再カウント
param = padr; //columnの必要な部分のみ送信
data = edit_voice[padr];
StoreMidi();
}
boundry[ch_no] &= ~(0b00000011 << column );
cw_ccw[ch_no] &= ~(0b00000011 << column );
}
}
}
boundry[ch_no] = 0;
cw_ccw[ch_no] = 0;
ppp = 0;
}
//**************************************************************
●前回のno[12][8]のテーブルを参照して、まず1行目と2行目の半分(bit4からbit7)にあるスイッチ(以下SW)について、ビットシフト演算により偶数ビットのSWの状態をみます。そのON/OFF状態をオペレータフラグ voice[155]に反映します。
●1行の中にSWとREが混在している上に、3行目以降はRE処理も書いているのでややこしいです。
●2行目の半分(bit0からbit3)以降はREのvoiceパラメータ確定と回転方向の判別・数値増減を行います。1行に4個のREがあるので、for文も0、2、4、6をキーにチェックします。
●余談ですが、C で for文は for ( ; ; )のスタイルですが、perlだと for ( 0, 2, 4, 6)という書き方もできます。変数に$をつけるとかの約束がありますが、Cに似ているので結構抵抗が少ないです。その分、つまづくことは何時もなんですが。しかし、最近、人気無いですね。
●for文の変数ですが、最初はswnum、その後 countとなり、すぐcolumnって統一性がないのまるわかり。これが試行錯誤プログラミングなのだ。
●セレクトされているOP番号が決まれば、簡単な計算でそのOP番号に関連するパラメータアドレスを算出しています。ややこしいことをせずにベタ書きの方がひょっとして良かったのではと思う今日このごろ。
●最後のほうでタイマをカウントしている部分がありますが、これはいわゆるウォッチドッグタイマで、REの数値を増減後の一定時間経過後にMIDIデータ(音楽データ)を送信することを考えています。そう、キーボード弾かなくてもいいのです。でも今回のテーマには沿わないので実装はしていません。
●ソースリストはこんな形よりもファイルをダウンロード出来るようにしておくのがいいですよね。このSSブログには簡単にできるような説明がありませんでした。Githubで登録するのを考えましたが時間がとれない。これからの課題にします。何しろ明日はセンター試験の2日目なんで・・・(別に関係ないけど)。
●1行の中にSWとREが混在している上に、3行目以降はRE処理も書いているのでややこしいです。
●2行目の半分(bit0からbit3)以降はREのvoiceパラメータ確定と回転方向の判別・数値増減を行います。1行に4個のREがあるので、for文も0、2、4、6をキーにチェックします。
●余談ですが、C で for文は for ( ; ; )のスタイルですが、perlだと for ( 0, 2, 4, 6)という書き方もできます。変数に$をつけるとかの約束がありますが、Cに似ているので結構抵抗が少ないです。その分、つまづくことは何時もなんですが。しかし、最近、人気無いですね。
●for文の変数ですが、最初はswnum、その後 countとなり、すぐcolumnって統一性がないのまるわかり。これが試行錯誤プログラミングなのだ。
●セレクトされているOP番号が決まれば、簡単な計算でそのOP番号に関連するパラメータアドレスを算出しています。ややこしいことをせずにベタ書きの方がひょっとして良かったのではと思う今日このごろ。
●最後のほうでタイマをカウントしている部分がありますが、これはいわゆるウォッチドッグタイマで、REの数値を増減後の一定時間経過後にMIDIデータ(音楽データ)を送信することを考えています。そう、キーボード弾かなくてもいいのです。でも今回のテーマには沿わないので実装はしていません。
●ソースリストはこんな形よりもファイルをダウンロード出来るようにしておくのがいいですよね。このSSブログには簡単にできるような説明がありませんでした。Githubで登録するのを考えましたが時間がとれない。これからの課題にします。何しろ明日はセンター試験の2日目なんで・・・(別に関係ないけど)。
飛ばして進めたので忘れていることが多いようで、まとまりがないです。一応、MIDIコントローラの話はここまで。家の中を探索すると梅酒とかりん酒がありました。寒くなってきたのでちょっとだけ飲んでみよう。
※このブログで書かれた内容によって生じた損害等の一切の責任を負いかねますので、予めご了承下さい。
コメント 0